3

I know people keep telling me to read the documentation, and I haven't got the hang of that yet. I don't specifically know what to look for inside the docs. If you have a tip on how to get used to reading the docs, give me your tips as a bonus, but for now here is my question. Say in a simple program if we allocate some chunk of memory I can free it once I am done, right? here is one such a program that does nothing, but allocates and deallocates memory in the heap.

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
char *s = malloc(10);
free(s);
return (0);
}

After we compile this, if we run valgrind we can see that everything is freed. Now, here is just a little bit of a twist to the previous program.

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
char *s = malloc(10);
s++;
free(s);
return (0);
}

Here, before I free it, I increment the address by one, and all hell breaks loose. Free doesn't seem to now that this chunk of memory was allocated (even though it is a subset of allocated memory). In case you want to see it, here is my error message.

*** Error in `./a.out': free(): invalid pointer: 0x0000000001e00011 ***
Aborted (core dumped). 

So this got me thinking.

  1. Does c keep track of memory's allocated on the heap
  2. If not, how does it know what to free and what to not?
  3. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?
  • The answer to the question in the title is No. – goodvibration Oct 29 '20 at 13:19
  • 1
    You can only free memory that has been returned from `malloc` etc. Calling free with anything else is undefined behaviour. – Jabberwocky Oct 29 '20 at 13:22
  • The answers to your bottom line questions are: 1. No. 2. It doesn't. This is the programmer's responsibility. 3. "It" doesn't have "such knowledge". And while it's possible to implement a memory-managed infrastructure (language, VM, etc) which will prevent memory leaks, it is not what the C language standard was designated for. There are design patterns built **on top** of C++, which handle that. You can also implement those design patterns in C, though it ain't gonna be a walk in the park. And there are higher-level languages like Java, which employ garbage collection to handle all of that. – goodvibration Oct 29 '20 at 13:22
  • @goodvibration 2. but if that is the case how does c throw an error when trying to free a memory that is not allocated by malloc, and works fine when used with a memory allocated with malloc – Hileamlak Yitayew Oct 29 '20 at 13:23
  • 2
    That's got nothing to do with C. It's the operating system's responsibility in general. If you wanna know how it's implemented behind the scenes, then AFAIK, in most cases, when you allocate a block of memory on the heap, the OS actually allocates a few more bytes at the beginning of that block, where it stores the length of that block and a pointer to the length block. So in essence, the heap is managed more or less as a linked list. When you delete a block by its address (pointer), the OS gets that meta data from the few bytes right before that address. – goodvibration Oct 29 '20 at 13:27
  • But again - this is not defined under the C language standard, so every platform (compiler + OS + HW) can implement it in a different manner. – goodvibration Oct 29 '20 at 13:28
  • When C runtime allocates a block of memory with `malloc`, it also reserves a small amount of memory just before the returned pointer, that contains just the minimal information about the allocation, needed to free that block when you call `free`. If you try to `free` a random pointer (not returned by `malloc` or `realloc` etc.) a run-time error will result. – printf Oct 29 '20 at 13:32
  • ok thanks guys, I will read more about it. That was the explanation I needed @goodvibration &pritnf – Hileamlak Yitayew Oct 29 '20 at 13:33
  • https://stackoverflow.com/questions/1957099/how-do-free-and-malloc-work-in-c This can help you. – Brian Oh Oct 29 '20 at 13:34
  • it is funny @printf I come across this problem , when I was implimenting my own custom _printf – Hileamlak Yitayew Oct 29 '20 at 13:36
  • 1
    I don't understand the downvote (and the lack of more upvotes): the question is well put and shows research. +1 – 0x5C91 Oct 29 '20 at 13:49
  • @scristalli, Thank you, I appreciate it, and I enjoy learning from all you pros out there. – Hileamlak Yitayew Oct 29 '20 at 13:53

2 Answers2

4

The C standard description of free says the following:

  1. The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Since you changed the pointer, it does not match a pointer returned by a memory management function (i.e. m/re/calloc), the behaviour is undefined, and anything can happen. Including the runtime library noticing that you've tried to free an invalid pointer, but the runtime is not required to do that either.


As for

  1. Does C keep track of memory's allocated on the heap

It might... but it does not necessarily have to...

  1. If not, how does it know what to free and what to not?

Well, if it does free the memory pointed to by a pointer, then it obviously need to have some kind of bookkeeping about the sizes of the allocations... but it does not need to be able to figure out if any pointers are still pointing to that memory area.

  1. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?

Usually memory is freed after the process exits by the operating system. That's not the problem. The real problem are the leaks that happen while the program is still running.

0

My knowledge is limited. But I think I can solve some of your question

  1. Does c keep track of memory's allocated on the heap

C does not track anything. The OS, however, tracks and knows which memory region are used and which is not.

  1. If not, how does it know what to free and what to not?

See how-does-free-know-how-much-to-free
Put it simplly. When calling malloc, you give it a size. malloc uses an extra 8 bytes right in front of the pointer it returns to "remember" this size information. When you free said pointer, free will know both the address and read 8 bytes before the pointer to get the size info, then happily release the memory to the operating system.

  1. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?

The OS knows the information. Thus when a C program exits, the OS will take in charge and free memory you didn't free explicitly.

*** Error in ./a.out': free(): invalid pointer: 0x0000000001e00011 *** Aborted (core dumped).`

As for this. I give of snippet of glibc free function glibc free function snippit
glibc malloc will allocate memory region in an aligned pattern, say 32 byte aligned. So when you did s++, it is not 32 byte aligned any more.
Now you may think what if i do s += 32; and set a pretending size information before s. I tried this. Sadly I can't naively trick glibc' free function. It has other information to prevent this. I stopped to dig in right now...

Dada
  • 6,313
  • 7
  • 24
  • 43
Zhaoyang
  • 49
  • 8
  • You might want to precise that the fact that malloc uses an extra _8_ bytes as headers is implementation dependent. Also, it would be nice if you could add a link to the source code of your screenshot, and copy-paste the code instead of the screenshot (I'll help you: [the code is here](https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4447-L4449). As to why you can't trick `free`: malloc has datastructures to keep track of free memory, to know when to call `sbrk` etc, and, as such, is not easily tricked. – Dada Jul 09 '21 at 07:22
  • @Dada It's helpful of you to give me the advise. Many thanks. – Zhaoyang Jul 12 '21 at 07:06