Tuesday, November 15, 2011

double free is dangerous

Today, a double free of a pointer caused a crash in the program, which is hard to detect. One of my colleagues helped me pin down the problem and fixed it.

As we all know, if a block memory is allocated through malloc() or new(), we must remember to free() or delete() the pointer (pointing to the memory block allocated) later. And it is perfectly legal in C/C++ to free/delete a null pointer. So we usually don't bother to check whether the pointer is null before freeing it. And fewer programmers will set the pointer to null after the memory is freed.

Yet, this is a bad practice. Consider the following scenario:
---
char *p = (char *)malloc(1024);
... //some string operations involving p
free(p);
free(p);
---
Definitely, it will cause a core dump. Here is the reason: After the first free(), the memory pointed to by p is deallocated and reclaimed by the system. But p is not set to null yet. In this case, it is called a dangling pointer. What is points to is undetermined and unknown. When the second free() is run on the dangling pointer, the system is tring to free a block of memory not in use any more! The best result you can expect is a core dump.

The solution is simple. Just set the pointer to null after it is freed. Usually, we wrap it up in a macro.
---
#define SAFE_FREE(p)        if ((p) != NULL) do {free((p)); (p) = NULL;} while (0)
---
It is a common practice to wrap up multiple statements of a macro into a do {...} while (0) loop, with no terminating semicolon.This allows the macro to be used like a single statement in any location, such as the body of an if statement, while still allowing a semicolon to be placed after the macro invocation without creating a null statement.

References:
http://stackoverflow.com/questions/2468853/freeing-memory-twice
http://en.wikibooks.org/wiki/C_Programming/Common_practices

No comments:

Post a Comment