How are we able to access the pointer after deallo

2020-01-29 02:45发布

问题:

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;
}

回答1:

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.



回答2:

Accessing a dangling pointer will result in undefined behavior. A dangling pointer is the one which is already freed.



回答3:

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.



回答4:

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?