Home > OS >  What happens when you call free(var) after malloc in C?
What happens when you call free(var) after malloc in C?

Time:02-19

I have a function which must be called multiple times and contain a string I have allocated using malloc. The first call to the function works fine, but the second call it appears that the first string was never "deleted" from memory. I had always thought that the "free" keyword meant it would completely free up the memory it was allocated to on the heap. What is free actually doing?

CodePudding user response:

C 2018 7.22.3.3 2 says, of free(ptr):

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.

That is all. It makes memory available for further allocation (the memory management software updates its records to note the memory is available for new uses). It is not required to change the memory (nor is it required not to change the memory), and it does not change ptr (although the “value” of ptr becomes invalid in C’s semantics).

CodePudding user response:

The C library function void free(void *ptr) de-allocates the heap memory previously allocated by a call to calloc, malloc, or realloc.

For an example:

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

int main(void)
{
    size_t my_data_length = 10;
    int *my_data = (int *)malloc(sizeof(int) * my_data_length);
    for (size_t i = 0; i < my_data_length; i  )
        my_data[i] = i * i;
    for (size_t i = 0; i < my_data_length; i  )
        printf("%d\n", my_data[i]);
    free(my_data);
    return 0;
}

The above code generates squares from 0 to 10, 10 is not included. So, I used free to de-allocate the heap memory I have used to store my_data.

If I didn't wrote free(my_data);, then also output would be same but under the hood some memory leaks will happen (modern OS manages the memory itself whenever a program exits without freeing its heap allocated memory).

For an example:

If I debug this code under valgrind, the output will be like this:

==29666== HEAP SUMMARY:
==29666==     in use at exit: 0 bytes in 0 blocks
==29666==   total heap usage: 2 allocs, 2 frees, 4,136 bytes allocated
==29666== 
==29666== All heap blocks were freed -- no leaks are possible
==29666== 
==29666== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Now, if I remove that free line then valgrind's output will be:

==29719== HEAP SUMMARY:
==29719==     in use at exit: 40 bytes in 1 blocks
==29719==   total heap usage: 2 allocs, 1 frees, 4,136 bytes allocated
==29719== 
==29719== Searching for pointers to 1 not-freed blocks
==29719== Checked 114,288 bytes
==29719== 
==29719== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29719==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29719==    by 0x109168: main (main.c:7)
==29719== 
==29719== LEAK SUMMARY:
==29719==    definitely lost: 40 bytes in 1 blocks
==29719==    indirectly lost: 0 bytes in 0 blocks
==29719==      possibly lost: 0 bytes in 0 blocks
==29719==    still reachable: 0 bytes in 0 blocks
==29719==         suppressed: 0 bytes in 0 blocks
==29719== 
==29719== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Which clearly indicates that a block of heap memory was not freed while exiting the application.

CodePudding user response:

What happens when you call ... malloc in C?

Let's look at a computer without MMU (on modern desktop computers, it is a bit more complicated):

There is some memory area called the "heap". You might imagine this "heap" as array of char:

char heap[10000];

This array is used for the data allocated by malloc.

When you call malloc(200), the operating system checks which range in the array with the requested size is currently not used. Let's say the range from heap[400] to heap[599] is currently not in use.

Then the operating system stores the following information somewhere:

  • The range 400...599 is no longer unused but used
  • The range starting at heap[400] is 200 bytes long

Then it returns the pointer &(heap[400]) (this is the value returned by malloc).

What happens when you call free(var) ... in C?

Let's say var=&(heap[400]).

The operating system reads the information that the range starting at heap[400] is 200 bytes long. (This information was stored during malloc.)

Then it stores the information that the range 400...599 is now free and can be used for future calls of malloc.

... but the second call it appears that the first string was never "deleted" from memory.

The operating system has only stored the information that the area from heap[400] to heap[599] is unused so it can be used in future calls of malloc.

Unless a special security variant of malloc or free is used, the values of these 200 bytes are not overwritten.

And after you called free(var), var will still point to heap[400] (assuming a computer without MMU)!

When you call malloc again with the same size (and no other program has called malloc in the meantime), it is very probable that the OS will find out that the range from heap[400] to heap[599] is free and return a pointer to heap[400].

And this range still contains your string (if no other program called malloc in the meantime) because it was not overwritten.

  •  Tags:  
  • c
  • Related