Have a look at this C code:
#include<stdio.h>
#include<stdlib.h>
int main(){
int *ptr_one;
ptr_one = (int *)malloc(sizeof(int));
if (ptr_one == 0){
printf("ERROR: Out of memory\n");
return 1;
}
*ptr_one = 25;
printf("%d\n", *ptr_one);
free(ptr_one);
printf("%d\n", *ptr_one);
return 0;
}
When I run this code, it gives this output:
25
25
Even after I free the pointer, why is it still giving 25 as output?
Read a lot more about undefined behavior (UB). Your code has some (you are not allowed to do something with a pointer after it has been free
-d).
Even after I free the pointer, why is it still giving 25 as output?
It is UB. You have bad luck. Be scared.
Read the C11 standard specification n1570.
You don't really need to understand how free
works (but you need to understand how you should use it). However, it usually uses some operating system specific system call dealing with virtual address space. On Linux, many C standard library implementations -e.g. GNU glibc or musl-libc - are free software (so you can download and study their source code), and their malloc
might sometimes get more virtual address space with system calls like mmap(2) (or the old sbrk(2)), and their free
might sometimes release some space with munmap(2).
What usually happens is that C dynamic memory allocation works differently for "large" and "small" memory zones. For small zones, the C library prefer to re-use previously free
-d ones in future malloc
-s. It gets (sometimes) from the OS a large chunk of memory (using mmap
) and split that chunk into pieces. When you free
a small zone, that zone is simply added to some collection of pieces, for future malloc
. So it still "exists" but using it is UB (and that explains the behavior your are observing).
The valgrind utility is a very useful tool to hunt memory related UB.