内存泄漏排查

内存泄漏排查

背景

在工作中发现一个tuexdo服务存在内存泄漏的情况,之前也尝试过用valgrind等工具查找,但是因为代码直接加载在tuexdo的服务中,不知道怎么直接启动,所以没有用valgrind。在经过查找资料后,决定自己写重写malloc/free等函数,打印出分配地址和释放地址,进行对比,如果发现只有malloc没有free,则能定位到相关代码

替换Linux中malloc的方法

参考资料

如何实现一个malloc

基础知识,介绍了Linux内存管理的基本知识,简单介绍了malloc的实现机制,并逐渐实现一个malloc

Memory Allocation Hooks

有用例,比man__malloc_hook 中的用例更适合

man__malloc_hook

malloc_hook钩子函数的官方文档

memory leak & double free如何排查?

首先介绍了如何定位调用函数的几种方法 其次介绍了收集内存分配和释放的两种方法,最后这两种方法都调试成功了
1. 通过宏替换掉发起内存分配的函数(malloc、realloc、calloc、memalgin、new),但是确定在于必须有源代码,否则无法替换
2. 在无代码情况下,用malloc钩子函数替换malloc函数,man__malloc_hook

拦截malloc、free等库函数(malloc钩子)

函数实现时参考了这里和官方页面用例(Memory Allocation Hooks)的代码

在应用程序中替换Linux中Glibc的malloc的四种方法

介绍了替换malloc的四种方法:
1. 使用环境变量LD_PRELOAD,使用LD_PRELOAD后,自己编写的malloc的加载顺序高于glibc中的malloc
2. malloc调试变量,即使用malloc钩子函数,优点是没有源代码的情况下也可以实现malloc替换,缺点是不适用于多线程环境中,本文主要通过该方法实现内存泄漏的排除
3. 编译自己的libmalloc.a,没看懂这个方法
4. 链接过程控制,即在gcc编译时,使用 –Wl –wrap,当查找某个符号时,它优先先解析__wrap_symbol, 解析不到才去解析symbol,这个方法尝试了但是没成功,参考:定制化的malloc/free

实现

根据memory leak & double free如何排查? 里面介绍的两种方法,首先实现了宏定义的方式,发现我们自己的代码里面没有分配了没释放的情况,然后采用了方法2,即写malloc_hook的方法,替换原malloc,在自己的malloc函数my_malloc中打印地址,my_free中也打印地址,通过awk脚本解析log日志,对比malloc的地址在后面是否有对应的free,如果没有,则打印出来包括调用地址在内的信息,进行进一步排除,发现是oracle的库文件函数在malloc,但是没有对应的函数会调用free函数释放这块内存,导致内存增长

代码

  • memcheck.h
    编写了一个memcheck.h文件,实现了malloc_hook(完整的memcheck.h文件里面还包括了宏定义和wrap_system函数的代码)

  • check.sh,check.awk脚本
    用于解析日志,其中check.awk脚本调用awk命令对日志进行文本解析,打印出只有malloc没有free的信息以及以*开头的行

代码在 tool-checkmemory

用法

Step 1.

在文件中包含 memcheck.h文件

#include "memcheck.h"

Step 2.

在main或只调用一次的函数中调用my_malloc_ini(),从这个函数开始,后面的malloc函数都会被my_malloc_hook函数,会print出相关信息,如果想要打印出注释信息,以*开头

int main(){
    my_init();
    char* ptr = (char*)malloc(4696); 
    //to do
    print("****start main****\n");
}

Step 3.

运行程序,将信息打印到指定的日志文件中,修改check.sh中的$log配置,指向你的日志文件

logs=~/logs/20170220.out //your log file

可以看到日志如下:

malloc 0x83c2128 from   0x804b418 size 4696
****start main****
malloc 0x83c2140 from   0xb79b29ad size 11
free   0x83bf518 from   0x4ee876
free   0x83bd510 from   0xb79b26b8
free   0x83bf680 from   0xb79b2fcc
malloc 0x83bd510 from   0xb79b3da6 size  7
realloc0x83bba60 from   0xb79c31be size  117 oldptr  0x83bba60
free   0x83bd510 from   0xb78ed599
free   0x83c2140 from   0xb79c3b6a

Step 4.

运行check.sh进行解析,会打印出有malloc/realloc但是没有对应free的地方,像这样:

0x8425f00 6201 0x804b418  4696
****start main****

每一行分别代表 %内存地址% %日志行数% %调用函数地址% %内存大小%
可以看出在代码0x804b418处,声明了大小为4696的内存,但是没有free

Step 5.

调用addr2line,查看0x804b418对应的源代码
[cindyhua@dev-SpyTux-68 tool-memcheck]$addr2line -e a.out -f 0x804b418
main
/main.c:4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值