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

1.问题

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

2.调试代码

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

2.1对malloc和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)多行宏定义需要使用使用转义字符’\’连接。

2.2对operator new和operator delete的重载

如果项目中使用了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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

29740
来自专栏钱塘大数据

理工男图解零维到十维空间,烧脑已过度,受不了啦!

让我们从一个点开始,和我们几何意义上的点一样,它没有大小、没有维度。它只是被想象出来的、作为标志一个位置的点。它什么也没有,空间、时间通通不存在,这就是零维度。

33830
来自专栏腾讯大讲堂的专栏

白底黑字or黑底白字,眼睛更喜欢哪一个?

12310
来自专栏腾讯NEXT学位

今天我就说三句话

11620
来自专栏前端桃园

知识体系解决迷茫的你

最近在星球里群里都有小伙伴说道自己对未来的路比较迷茫,一旦闲下来就不知道自己改干啥,今天我这篇文章就是让你觉得一天给你 25 个小时你都不够用,觉得睡觉都是浪费...

21840
来自专栏web前端教室

你可以从面试中学到什么?

讲一下我对面试的一些。。。“偏见”,哈哈,熟悉我的同学们一定要批判的读接下来的内容哈。

12300
来自专栏钱塘大数据

中国互联网协会发布:《2018中国互联网发展报告》

在2018中国互联网大会闭幕论坛上,中国互联网协会正式发布《中国互联网发展报告2018》(以下简称《报告》)。《中国互联网发展报告》是由中国互联网协会与中国互联...

13750
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

18130
来自专栏微信公众号:小白课代表

不只是软件,在线也可以免费下载百度文库了。

不管是学生,还是职场员工,下载各种文档几乎是不可避免的,各种XXX.docx,XXX.pptx更是家常便饭,人们最常用的就是百度文库,豆丁文库,道客巴巴这些下载...

44630
来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.2K20

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励