前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C/C++代码调试:快速定位内存的申请和释放的位置

C/C++代码调试:快速定位内存的申请和释放的位置

作者头像
恋喵大鲤鱼
发布2018-08-03 16:34:38
8380
发布2018-08-03 16:34:38
举报
文章被收录于专栏:C/C++基础C/C++基础

1.问题

如果大型项目中出现类似于*** glibc detected *** logcacheinit: double free or corruption (fasttop): 0x00000000017db7f0 ***的错误。更糟糕的是项目既是多线程又是多个节点分布式运行的话,调试定位double free实在让人头痛。内核在程序崩溃的时候,这个信息只给出了被释放两次的内存地址,却没有给出程序出现两次内存释放的具体位置,这就需要我们自己动手排查。

2.调试代码

通过如下代码,对malloc和free进行定位并打印出具体的内存地址,可以根据内核提示的内存地址快速查找到double free的代码位置。

2.1对malloc和free的宏替换

代码语言:javascript
复制
#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)多行宏定义需要使用使用转义字符’\’连接。

2.2对operator new和operator delete的重载

如果项目中使用了new和delete来申请和释放内存,那么需要对operator new和operator delete进行重载。代码如下。

代码语言:javascript
复制
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的位置信息呢?那么需要下面的宏:

代码语言:javascript
复制
#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的自定义参数重载并不能手动调用。例如:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年01月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.问题
  • 2.调试代码
    • 2.1对malloc和free的宏替换
      • 2.2对operator new和operator delete的重载
      • 参考文献
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档