Does c keep track of allocated heap memory?

Viewed 288

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?
2 Answers

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.

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...

Related