As per my understanding,
free() is used to deallocate the memory that we allocated using malloc before.
In my following snippet, I have freed the memory i have allocated. But i was able to access the pointer even after freeing? How it is possible?
How free works internally?
#include<iostream>
using namespace std;
int main()
{
int *p=(int *)malloc(sizeof(int));
*p=17;
free(p);
*p=*p+1;
printf("\n After freeing memory :: %d ",*p );
return 0;
}
You can certainly continue to use p
after calling free(p)
and nothing will stop you. However the results will be completely undefined and unpredictable. It works by luck only. This is a common programming error called "use after free" which works in many programs for literally years without "problems" -- until it causes a problem.
There are tools which are quite good at finding such errors, such as Valgrind.
Accessing a dangling pointer will result in undefined behavior.
A dangling pointer is the one which is already freed.
After free(p)
, p
is a dangling pointer which points to no where. free()
just releases the memory block allocated by malloc()
and it doesn't change the value of pointer pointing to heap in that process address space. On some platforms you might get segfault if you try dereferencing pointer after freeing. Its good practice if you assign pointer p
to NULL
after freeing.
In most systems and standard libraries, malloc
is optimized by allocating a larger chunk of memory than required (up to 64K on some systems) from the OS, and then internally disbursing it as per requirement from this pool. The same applied to the deallocation (free
) as well, in that, the free
'd memory isn't freed, but put back in the memory pool, in case another request comes in, in which case the pool is reused.
Thus, the call to free
hasn't actually freed the memory from the process's address space and is thus accessible even after free.
My understanding as to why this is done is that system calls are expensive, so the initial call to malloc
will make a system call for enough memory that future requests for malloc
do not immediately trigger another system call for more memory.
As for further reading, please take a look at this page on Wikipedia, How do malloc() and free() work? and How is malloc() implemented internally?