How to solve a double free problem by writing a wrapper function with name free so that i need not change every free call in my source code?
Don't do that.
No, really. Fix the actual problem. Once free() has been called on a pointer, your code should not be holding on to it for any reason. Null it out so you can't free it again; this will make any other problems caused by stale pointer dereferencing visible too.
Don't do that
An easy way is to define your wrapper function and #define free to call your function instead.
#undef free
#define free(x) wrapper_free(x)
/* ... */
int *data = malloc(42);
free(data); /* effectively calls wrapper_free(data) */
but ... don't do that!
I agree with the other posts that say you shouldn't. Mainly, it'll be much more confusing for someone to look at your code and try to figure out what's going on (when they're used to see free only freeing memory).
If you're looking for a single line piece of code that will allow you to free and clear a pointer, I'd recommend using a macro, though there are other ways of doing this (creating a method that takes a pointer to your pointer).
#define FREEANDCLEAR(pointer)\
{\
free(pointer);\
pointer = 0;\
}
EDIT As Christoph mentioned in a comment, you can also make sure a user uses the macro like a function (ends the line with a semicolon by using a do while like this:
#define FREEANDCLEAR(pointer)\
do {\
free(pointer);\
pointer = 0;\
} while(0)
which will execute once and require an ending semicolon.
Look through the answers to the stackoverflow question, "Write your own memory manager".
Using the tools or techniques in those answers will let you incorporate a memory manager that checks for these types of problems so you can identify and fix them (as many other answers to your question indicate, it's not a good idea to use something like this as a workaround).
The following code intercepts calls to malloc()
, realloc()
and calloc()
for logging.
When calling free()
, it checks if the memory was previously allocated with one of these functions. If not, the program will be terminated. Freeing a null pointer will be reported, but execution will continue.
Header memdebug.h
:
#undef free
#define free(PTR) memdebug_free(PTR, #PTR, __FILE__, __func__, __LINE__)
#undef malloc
#define malloc(SIZE) memdebug_log(malloc(SIZE))
#undef realloc
#define realloc(PTR, SIZE) memdebug_log(realloc(PTR, SIZE))
#undef calloc
#define calloc(COUNT, SIZE) memdebug_log(calloc(COUNT, SIZE))
#ifndef MEMDEBUG_H
#define MEMDEBUG_H
extern void memdebug_free(void *ptr, const char *ptr_arg, const char *file,
const char *func, int line);
extern void *memdebug_log(void *ptr);
#endif
Source memdebug.c
:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef MEMDEBUG_TABLE_SIZE
// log 16k allocations by default
#define MEMDEBUG_TABLE_SIZE 0x4000
#endif
static void *alloc_table[MEMDEBUG_TABLE_SIZE];
static size_t top;
void *memdebug_log(void *ptr)
{
assert(top < sizeof alloc_table / sizeof *alloc_table);
alloc_table[top++] = ptr;
return ptr;
}
void memdebug_free(void *ptr, const char *ptr_arg, const char *file,
const char *func, int line)
{
if(!ptr)
{
fprintf(stderr,
"%s() in %s, line %i: freeing null pointer `%s` -->continue\n",
func, file, line, ptr_arg);
return;
}
for(size_t i = top; i--; )
{
if(ptr == alloc_table[i])
{
free(ptr);
--top;
if(i != top) alloc_table[i] = alloc_table[top];
return;
}
}
fprintf(stderr,
"%s() in %s, line %i: freeing invalid pointer `%s`-->exit\n",
func, file, line, ptr_arg);
exit(EXIT_FAILURE);
}
Apart from all the other answers and references to memory management developement etc.
When double free occurs there are errors in the code that indicates that things are not done in the right order, etc.
When I started working with Java some 10 years ago, everybody praised Java since you did not have to bother about new/delete.
I was bothered (as I was used to develop in C/C++), since suddenly all the open/close, create/destroy, lock/unlock patterns that shows up in so many ways in software apart from malloc/free could be broken since everybody believed that all cleanup was automatic.
So when you have these problems, you probably have other problems as well sooner or later. Resources held up, DB connections being consumed, files locked on filesystems.
Double free is a signal that your program does not have a good structure, e.g things being allocated in one layer and freed in another.