dmalloc是一个简单易用的C/C++内存leak检查工具,以一个运行库的方式发布。能够检查出直到程序运行结束还没有释放的内存,并且能够精确指出在哪个源文件的第几行。
dmalloc 主页: http://dmalloc.com
根据官方网址描述支持常见平台:AIX, BSD/OS, DG/UX, Free/Net/OpenBSD, GNU/Hurd, HPUX, Irix, Linux, MS-DOG, NeXT, OSF, SCO, Solaris, SunOS, Ultrix, Unixware, Windoze, and even Unicos on a Cray T3E
目前最新版本: dmalloc-5.5.2.tgz
下载,解压,编译,安装,关于编译安装可参考
#linux# gdb交叉编译arm-linux-gnueabihf-gdb
https://blog.csdn.net/xiaoting451292510/article/details/105166739
编译过程中可能会提示以下错误
dmalloc.h:484:7: error: expected identifier or ‘(’ before ‘__extension__’ char *strndup(const char *string, const DMALLOC_SIZE len);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #ifndef DMALLOC_STRDUP_MACRO /* * DMALLOC_PNT strdup * * DESCRIPTION: * * Overload of strdup(3). Allocate and return an allocated block of * memory holding a copy of a string. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. */ extern char *strdup(const char *string); /* * DMALLOC_PNT strndup * * DESCRIPTION: * * Overload of strndup(3). Allocate and return an allocated block of * memory holding a copy of a string with a maximum length. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. * * len -> Length of the string to duplicate. */ extern char *strndup(const char *string, const DMALLOC_SIZE len); #endif /* ifndef DMALLOC_STRDUP_MACRO */ |
请将源码中的宏DMALLOC_STRDUP_MACRO范围将strndup包裹起来,一般情况下也不建议使用。#linux# #字符串处理# strdup、strndup、strndupa、strdupa
ubuntu16.04-x86-64 安装到默认路径(一般不建议安装到默认路径,请尽量进行指定路径安装)
1 2 3 | ./configure make threadscxx make installthcxx |
ubuntu16.04-x86-64安装到当前路径
1 2 3 | ./configure --prefix=/home/cll/99_temp/memory_leak/dmalloc/dmalloc-5.5.2_ubuntu16.04-x86-64 make threadscxx make installthcxx |
arm-linux-gnueabihf安装到当前路径
1 2 3 | ./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- CC=arm-linux-gnueabihf-gcc --prefix=/home/cll/99_temp/memory_leak/dmalloc/dmalloc-5.5.2_arm-linux-gnueabihf make threadscxx make installthcxx |
./configure --prefix=/home/cll/99_temp/memory_leak/dmalloc/dmalloc-5.5.2_ubuntu16.04-x86-64
根据相关提示可以编译不同的相应版本
1 2 3 | To make the thread version of the library type 'make threads' To make the C++ version of the library type 'make cxx' To make the shared version of the library type 'make shlib' |
将库xx.a嵌入运行程序,makefile里面增加:-DDMALLOC -DDMALLOC_FUNC_CHECK -ldmallocthcxx。如果是C程序把-ldmallocthcxx修改为-ldmalloc即可,如加入以下红色部分
g++ -Wall -g -DDMALLOC -DDMALLOC_FUNC_CHECK -ldmallocthcxx memleak_test.cpp memleak_test1.cpp memleak_test2.cpp -o memleak_test
执行dmalloc,获取环境变量信息,并把它设置为环境变量。
1 2 3 | $ ./dmalloc -b -l logfile -i 100 low DMALLOC_OPTIONS=debug=0x4e48503,inter=100,log=logfile export DMALLOC_OPTIONS |
执行需要检测的程序,会在同一个目录下生成一个logfile文件,里面就是内存泄漏的信息。
1 | ./memleak_test |
对于任何非malloc/free情況下所发生的内存泄露问题,mtrace并不能找出来。也就是对于new的内存,只能检测出有泄露,但不能定位。
dmalloc支持两种使用方式。
- 调试程序只进行dmalloc静态库的编译链接(上面介绍的就是这种方式),这种方式的好处是对于代码量比较大的现有程序,无需要关心每个.c文件的编译细节,只需要将dmalloc静态库放在程序依赖的最后面即可。但缺点是针对不同CPU体系需要了解基本的函数返回地址汇编实现,同时即使得到了泄露源的地址变量,但也需要借助gdb、objdump或map文件等手段得到该泄露源的真正文件/行号或函数范围。
- 使用dmalloc静态库编译链接外,还需要在每个要调试的.c程序文件中加入dmalloc.h文件的引用,这种方式的原理是使用dmalloc.h头文件的宏定义将需要调试的.c程序文件中的malloc替换为dmalloc_malloc,这种方式的好处和上面方式正好相反,不需要了解不同CPU体系的汇编,不需要借助gdb等工具,因为编译宏的替换可以直接使用__FILE__、__LINE__宏,所以得到的调试信息直接是可以看到的文件名/行号。但缺点也很明显,需要保证所有需要调试的.c程序文件,都要引用了dmalloc.h头文件。
只进行dmalloc静态库的编译链接
内存泄露信息如下:
1588152214: 107: Dumping Not-Freed Pointers Changed Since Start:
1588152214: 107: not freed: '0x7fb6d1608f08|s1' (36 bytes) from 'unknown'
1588152214: 107: not freed: '0x7fb6d1608f48|s1' (32 bytes) from 'unknown'
1588152214: 107: not freed: '0x7fb6d1608f88|s1' (28 bytes) from 'unknown'
1588152214: 107: not freed: '0x7fb6d1608fc8|s1' (24 bytes) from 'unknown'
1588152214: 107: not freed: '0x7fb6d160bf48|s1' (20 bytes) from 'unknown'
使用dmalloc静态库编译链接外,还需要在每个要调试的.c程序文件中加入dmalloc.h文件的引用
内存泄露信息如下:
1588151651: 107: 200 1 0 0 memleak_test.cpp:72
1588151651: 107: 100 1 0 0 memleak_test.cpp:71
1588151651: 107: 100 1 0 0 memleak_test.cpp:68
1588151651: 107: 100 1 100 1 memleak_test.cpp:65
1588151651: 107: 100 1 100 1 memleak_test.cpp:67
1588151651: 107: 100 1 0 0 memleak_test.cpp:74
1588151651: 107: 100 1 0 0 memleak_test.cpp:66
1588151651: 107: 100 1 0 0 memleak_test.cpp:64
1588151651: 107: 50 1 0 0 memleak_test.cpp:70
1588151651: 107: 961 11 201 3 Total of 11
1588151651: 107: Dumping Not-Freed Pointers Changed Since Start:
1588151651: 107: not freed: '0x7f1bc74d9f08|s1' (36 bytes) from 'unknown'
1588151651: 107: not freed: '0x7f1bc74d9f48|s1' (32 bytes) from 'unknown'
1588151651: 107: not freed: '0x7f1bc74d9f88|s1' (28 bytes) from 'unknown'