Linux C 编程内存泄露检测工具 末蓝、 2022-06-18 01:22 356阅读 0赞 ## 前言 ## 所有使用动态内存分配(dynamic memory allocation)的程序都有机会遇上内存泄露(memory leakage)问题,在Linux里有三种常用工具来检测内存泄露的情況,包括: 1. mtrace 2. dmalloc 3. memwatch ## 1. mtrace ## mtrace是三款工具之中是最简单易用的,mtrace是一个C函數,在<mcheck.h>里声明及定义,函数原型为: void mtrace(void); 其实mtrace是类似malloc\_hook的 malloc handler,只不过mtrace的handler function已由系统为你写好,但既然如此,系统又怎么知道你想将malloc/free的记录写在哪里呢?为此,调用mtrace()前要先设置 MALLOC\_TRACE环境变量: \#include <stdlib.h> .... setenv("MALLOC\_TRACE", "output\_file\_name", 1); ... 「output\_file\_name」就是储存检测结果的文件的名称。 但是检测结果的格式是一般人无法理解的,而只要有安装mtrace的话,就会有一名为mtrace的Perl script,在shell输入以下指令: mtrace \[binary\] output\_file\_name 就会将output\_file\_name的內容转化成能被理解的语句,例如「No memory leaks」,「0x12345678 Free 10 was never alloc」诸如此类。 例如以下有一函数:(暂且放下single entry single exit的原则) \#include <stdio.h> \#include <stdlib.h> \#include <errno.h> \#include <mcheck.h> int main() \{ char \*hello; setenv("MALLOC\_TRACE", "output", 1); mtrace(); if ((hello = (char \*) malloc(sizeof(char))) == NULL) \{ perror("Cannot allocate memory."); return -1; \} return 0; \} 执行后,再用mtrace 将结果输出: \- 0x08049670 Free 3 was never alloc'd 0x42029acc \- 0x080496f0 Free 4 was never alloc'd 0x420dc9e9 \- 0x08049708 Free 5 was never alloc'd 0x420dc9f1 \- 0x08049628 Free 6 was never alloc'd 0x42113a22 \- 0x08049640 Free 7 was never alloc'd 0x42113a52 \- 0x08049658 Free 8 was never alloc'd 0x42113a96 Memory not freed: \----------------- Address Size Caller 0x08049a90 0x1 at 0x80483fe 最后一行标明有一个大小为1 byte的内存尚未释放,大概是指「hello」吧。 若我们把该段内存释放: \#include <stdio.h> \#include <stdlib.h> \#include <errno.h> \#include <mcheck.h> int main() \{ char \*hello; setenv("MALLOC\_TRACE", "output", 1); mtrace(); if ((hello = (char \*) malloc(sizeof(char))) == NULL) \{ perror("Cannot allocate memory."); return -1; \} free(hello); return 0; \} 结果如下: \- 0x080496b0 Free 4 was never alloc'd 0x42029acc \- 0x08049730 Free 5 was never alloc'd 0x420dc9e9 \- 0x08049748 Free 6 was never alloc'd 0x420dc9f1 \- 0x08049668 Free 7 was never alloc'd 0x42113a22 \- 0x08049680 Free 8 was never alloc'd 0x42113a52 \- 0x08049698 Free 9 was never alloc'd 0x42113a96 No memory leaks. mtrace的原理是记录每一对malloc-free的执行,若每一个malloc都有相应的free,则代表没有内存泄露,对于任何非malloc/free情況下所发生的内存泄露问题,mtrace并不能找出来。 ================================================================================================ ## Memwatch简介 ## 在三种检测工具当中,设置最简单的算是memwatch,和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域。请往[http://www.linkdata.se/sourcecode.html][http_www.linkdata.se_sourcecode.html]下载最新版本的Memwatch。 ## 安装及使用memwatch ## 很幸运地,memwatch根本是不需要安装的,因为它只是一组C程序代码,只要在你程序中加入memwatch.h,编译时加上-DMEMWATCH -DMW\_STDIO及memwatch.c就能使用memwatch,例如: gcc -DMEMWATCH -DMW\_STDIO test.c memwatch.c -o test ## memwatch输出結果 ## memwatch 的输出文件名称为memwatch.log,而且在程序执行期间,所有错误提示都会显示在stdout上,如果memwatch未能写入以上文件,它会尝试写入memwatchNN.log,而NN介于01至99之间,若它仍未能写入memwatchNN.log,则会放弃写入文件。 我们引用第一篇(mtrace)中所使用过的有问题的代码: \#include <stdio.h> \#include <stdlib.h> \#include <errno.h> \#include <memwatch.h> int main() \{ char \*hello; setenv("MALLOC\_TRACE", "output", 1); mtrace(); if ((hello = (char \*) malloc(sizeof(char))) == NULL) \{ perror("Cannot allocate memory."); return -1; \} return 0; \} 然后在shell中输入以下编译指令: gcc -DMEMWATCH -DMW\_STDIO test.c memwatch.c -o test memwatch.log的內容如下: ============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh ============= Started at Sat Jun 26 22:48:47 2004 Modes: \_\_STDC\_\_ 32-bit mwDWORD==(unsigned long) mwROUNDALLOC==4 sizeof(mwData)==32 mwDataSize==32 Stopped at Sat Jun 26 22:48:47 2004 unfreed: <1> test.c(9), 1 bytes at 0x805108c \{FE .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .\} Memory usage statistics (global): N)umber of allocations made: 1 L)argest memory usage : 1 T)otal of all alloc() calls: 1 U)nfreed bytes totals : 1 文件指出,在test.c被执行到第9行时所分配的内存仍未被释放,该段内存的大小为1 byte。 ## Memwatch使用注意 ## Memwatch 的优点是无需特別配置,不需安装便能使用,但缺点是它会拖慢程序的运行速度,尤其是释放内存时它会作大量检查。但它比mtrace和dmalloc多了 一项功能,就是能模拟系统内存不足的情況,使用者只需用mwLimit(long num\_of\_byte)函数来限制程式的heap memory大小(以byte单位)。 最详细的使用说明(包括优点缺点,运行原理等)已在README中列出,本人强烈建议各位读者参考该文件。 ==================================================================================================== [Linux下的内存泄露检测工具][Linux] Linux下的内存泄露检测工具 01) MallocDebug 02) Valgrind 03) Kcachegrind 04) ElectricFence. 05) dmalloc 06) ccmalloc 07) LeakTracer 08) memprof 09) BoundsChecker.\[prop\] 10) mprof. 11) Insure.\[prop\] 12) dbx. (for Sparc) 13) YAMD 14) Njamd 15) Mpatrol [http_www.linkdata.se_sourcecode.html]: http://www.linkdata.se/sourcecode.html [Linux]: http://www.cnitblog.com/flutist1225/articles/19239.html
还没有评论,来说两句吧...