views:

639

answers:

9

AFAIK, freeing a NULL pointer will result in nothing. I mean nothing is being done by the function free.

Still, I do see some statements where people say that one of the scenarios where memory corruption can occur is "freeing memory twice".

Is this still true?

+7  A: 

This is undefined behavior, that can result in heap corruption or other severe consequences.

free() for a null pointer simply checks the pointer value inside and returns. That check will not help against freeing a block twice.

Here's what happens usually. The heap implementation gets the address and tries to "take ownership" of the block at that address by modifying its own service data. Depending on the heap implementation anything can happen. Maybe it works and nothing happens, maybe the service data is corrupted and you've got heap corruption.

So don't do it. It's undefined behavior. Whatever bad things can happen.

sharptooth
I would also say explicitly that `free` ing a pointer doesn't (neceaarily) change it's value and in general it's not null after the 'free' (which is why the second `free` causes corruption).
Ari
+4  A: 

Yes, "undefined behavior" which almost always results in a crash. (while "undefined behavior" by definition means "anything", various types of errors often behave in quite predictable ways. In case of free(), the behavior is invariably segfault or respective "memory protection error" characteristic to the OS.)

Same if you free() a pointer to anything else than NULL or something you malloc'd.

char x; char* p=&x; free(p); // crash.

SF.
+1 Crash 101 there.
kenny
You are too optimistic on the results of undefined behavior.
Roger Pate
I'm with Roger. In fact, freeing something twice almost never results in a crash at the point the free takes place, which makes it one of the most difficult bugs to track down.
anon
+2  A: 

free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is NULL, no operation is performed.

So, you get undefined behavior, and anything could happen.

nos
A: 

If you are using CRT, every allocation and deallocation is redirected to debugging routines enabling you to locate context of such 'second memory freeing' and other memory management problems.

Janusz Lenar
+12  A: 
int *p = malloc(sizeof(int));
//value of p is now lets say 0x12345678

*p = 2;
free(p); //memory pointer is freed, but still value of p is 0x12345678
         //now, if you free again, CRASH!BOOM!.

So, after free ing the first time,
you should do p = NULL , so if (by any chance), free(p) is called again, nothing will happen.


See comments for more.

N 1.1
+1 for correctness of the answer, even if I disagree in setting the pointer to NULL right after, that could hide a standing bug (calling `free` the second time) and I'd rather have it fail hard and fast so that the bug can be handled than hidden.
David Rodríguez - dribeas
@David: I totally agree, if `free` is called twice on a pointer, it is a (somewhat) bad implementation.
N 1.1
@David: That's a good strategy as long as you know how to debug 'free-twice' situations. If you don't, I'd rather nullify the pointer right after freeing and check it for nullness just before every `free` statement.
Janusz Lenar
@nvl: Yeah, that's why you call it a **bug** ;D
Janusz Lenar
@malleor: doing your way, if you nullify pointer right after freeing, there is no need to check before `free` statement
N 1.1
@malleor: having the double free kill the application you know that a pointer you are considering to be valid is actually not valid, hidding it can lead to situations where you dereference a null pointer and operate on it, which is undefined behavior (and depending on the system might just silently provide incorrect results). Debugging a crash is always simpler than debugging an incorrect value.
David Rodríguez - dribeas
@nvl: there is, if you want to find the bug - you're freeing twice! that was David's point.
Janusz Lenar
@malleor: well, i would go by "debugging the crash" way.
N 1.1
@David: well, i disagree, but that's a matter of preference. i prefer debugging online, e.g. after debug break inside CRT assertion, i.e. `_ASSERTE(ptr!=NULL)`.
Janusz Lenar
@David: It's a tradeoff. I think leaving the pointer pointing to freed memory makes it more likely to hide errors where the pointer is used afterward, as dereferencing the null pointer is often more likely to crash. Double-freeing is undefined behavior as well, and it often won't lead to an immediate crash either.
jamesdlin
Setting p to NULL after freeing doesn't help with any of the other n pointers to that data you also had hanging around. So you still need to know how to debug a double-free.
Vicky
+1  A: 

Hi, 1) Handling of dynamic memory is not done by compiler. There are run-time libraries which take care of this. For eg. : glibc provides APIs like malloc and free, which internally make system calls(sys_brk) to handle the heap area.

2) Freeing same memory twice refers to a condition like this : Suppose you have char *cptr;

You allocate memory using : cptr = (char *) malloc (SIZE);

Now, when you no longer need this memory, you can free it using this : free(cptr);

Now here what happens is the memory pointed to by cptr is free for use.

Suppose at a later point of time in the program you again call a free(cptr), then this is not a valid condition. This scenario where you are freeing the same memory twice is know as "freeing a memory twice" problem.`

Furquan
+15  A: 

Freeing memory does not set the pointer to the memory that was freed to null - it remains pointing to the memory it used to own, but which has now had ownership transferred back to the heap manager. Freeing it again is not, therefore, the same as saying free(NULL), and will result in undefined behaviour.

anon
+1  A: 

When you call free on a pointer, your pointer will not get set to NULL. The free space is only given back to a pool to be available for allocation again. Here an example to test:

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

int main(){
    int* ptr = (int*)malloc(sizeof(int));
    printf("Address before free: %p\n", ptr);
    free(ptr);
    printf("Address after free: %p\n", ptr);
    return 0;
}

This program outputs for me:

Address before free: 0x950a008
Address after free: 0x950a008

and you can see, that free did nothing to the pointer, but only told the system that the memory is available for reuse.

Lucas
A: 

To avoid free twice i alway using MACRO for free memory:

#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF( _p )  \
if( _p )              \
{                     \
        free( _p );   \
        _p = NULL;    \
}

this macro set p = NULL to avoid dangling pointer.

nguyendat
This is a nice hack but I'd rather try to fix the actual cause. If free() get called twice on the same variable, this is clearly a bug.