What does the free() function actually do?

Viewed 109

I'm using VScode to practice C and i'm trying to find what exactly does the free() function do to the pointer and the value inside that pointer. Here is my test code

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>


int main(void)
{
 int *n = malloc(sizeof(int));
 *n = 1;
 printf("%p %i\n",n, *n);
 free (n);
 printf("%p %i\n",n, *n);


 return 0;
}

when i run the code, here is what i get

0x56405d2e72a0 1
0x56405d2e72a0 1678103271

what i wanted to know is why is the pointer still the same but the value inside have been changed to some kind of garbage value and what does free() explicitly do to the memory ?

4 Answers

free() doesn't change the pointer - it only allows memory pointed by the pointer to be used by other processes. This means that there won't be any changes until another process says "I want to store some value in 0x56405d2e72a0". The reason why that is good is because now you're allowing other apps and programs to use more space. That's also why using a pointer after it's been freed is considered undefined behavior (because that memory could be changed at any moment)

From the C Standard you can read:

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.

For a beginner, the mysteries of malloc() and free() are best just trusted if they are respected and used appropriately.

I just ran this

#include <stdio.h>
#include <stdlib.h> // for 'exit()'

int main() {
    char *p;

    p = malloc( sizeof *p );
    if( p == NULL ){
        fprintf( stderr, "malloc failed\n" );
        exit( EXIT_FAILURE );
    }
    printf( "%p\n", p );
    free( p );

    p = malloc( sizeof *p );
    if( p == NULL ){
        fprintf( stderr, "malloc failed\n" );
        exit( EXIT_FAILURE );
    }
    printf( "%p\n", p );
    free( p );

    return 0;
}

Output

00881420
00881450

Notice that malloc() chose to issue a different block of memory in the second call even though there was no apparent "heap activity" between one free() and the following malloc().

Notice, too, that the "size" requested is defined by the size that the awaiting pointer should point at. (Also, fewer parentheses!) The declaration of 'p' could be changed to int, long or double or even a large, complex struct with only a single line changed in the code above.

Comments on your code - Don't use more #include statements than you need in any given source file, and "watch the whitespace". When source files become more complex, you will want to already have good style habits.

Finally, Always check the "return codes" from library functions. Always.

Calling free() makes memory previously allocated (by malloc(), realloc() or calloc() available for reallocation.

Behind the scenes free() will return the memory to whatever container is being used to record the available memory.

It may return memory to the Operating System for reallocation to other processes but a typical call just records it as available for reallocation.

Internally it may combine adjacent free areas into larger areas that can be split or allocated again later.

If you imagine there's a linked list of 'free' variable sized pieces of free memory and malloc() returns one of those or restructures one into a piece of suitable size and some spare then think of free handed that back and linking it in.

Related