如果大型项目中出现类似于*** glibc detected *** logcacheinit: double free or corruption (fasttop): 0x00000000017db7f0 ***的错误。更糟糕的是项目既是多线程又是多个节点分布式运行的话,调试定位double free实在让人头痛。内核在程序崩溃的时候,这个信息只给出了被释放两次的内存地址,却没有给出程序出现两次内存释放的具体位置,这就需要我们自己动手排查。
通过如下代码,对malloc和free进行定位并打印出具体的内存地址,可以根据内核提示的内存地址快速查找到double free的代码位置。
#define free(p) { \
printf("@@%s:%d:%s():free(0x%lx)\n", __FILE__, __LINE__, \
__func__, (unsigned long)p); \
free(p); \
}
#define malloc(size) ({ \
void* ptr=malloc(size);\
printf("@@%s:%d:%s():malloc(0x%lx)\n", __FILE__, __LINE__, \
__FUNCTION__, (unsigned long)ptr); \
ptr; \
})
注意事项:
(1)__FILE__,__LINE__,__FUNCTION__
是编程语言内置宏定义,编译时会被编译器替换成代码所在的文件名称,行号和所在函数名。
(2)多行宏定义需要使用使用转义字符’\’连接。
如果项目中使用了new和delete来申请和释放内存,那么需要对operator new和operator delete进行重载。代码如下。
void* operator new(size_t size, const char *file, int line,const char *function) throw (std::bad_alloc){
void * ptr=malloc(size);
printf("&&%s:%d:%s:new(size=%u)=%p\n",file,line,function,size,ptr);
if(ptr==NULL)
throw std::bad_alloc();
return ptr;
}
void* operator new[](size_t size,const char *file, int line,const char *function) throw (std::bad_alloc){
void * ptr=malloc(size);
printf("&&%s:%d:%s:new[](size=%u)=%p\n",file,line,function,size,ptr);
if(ptr==NULL)
throw std::bad_alloc();
return ptr;
}
void operator delete(void * p) throw()
{
free(p);
}
void operator delete[] (void * p) throw()
{
free(p);
}
对全局的operator new和operator delete函数重载完成后,如何才能获取调用new和delete的位置信息呢?那么需要下面的宏:
#define new new(__FILE__, __LINE__,__FUNCTION__)
#define delete ({\
printf("&&%s:%d:%s()",__FILE__,__LINE__,__FUNCTION__);\
}),delete
注意事项:
(1)delete或者delete[]打印内存地址时,需要依赖对free的宏定义;
(2)delete的使用基本和new一致,包括operator delete的重载方式这些都相似,只不过它的参数是void*,返回值为void。但是有一点需要注意,operator delete的自定义参数重载并不能手动调用。例如:
void* operator new(size_t size, int x)
{
cout<<" x = "<<x<<endl;
return malloc(size);
}
void operator delete(void* p, int x)
{
cout<<" x = "<<x<<endl;
free(p);
}
如下调用是无法通过的:
A* p = new(3) A;//Ok
delete(3) p;//error C2541:
上面对delete的宏就是用来解决这个问题的。
[1]http://blog.csdn.net/wudaijun/article/details/9273339
[2]http://blog.csdn.net/cangyingzhijia/article/details/8613177
[3]http://blog.csdn.net/wx3046/article/details/5792505