我在Linux编程中通常使用三种方法检测内存泄漏。
第一种方法是阅读程序源代码,打印和查看日志,观察分析程序的执行。
第二种方法使用valgrind:
假设名为mytest的程序可能有内存泄漏的情况。
那么执行命令:
valgrind -v --tool=memcheck --leak-check=full ./mytest
valgrind会打印出很多信息,比较重要的摘录如下:
==3127== malloc/free: in use at exit: 256 bytes in 1 blocks.
==3127== malloc/free: 4 allocs, 3 frees, 480 bytes allocated.
==3127==
==3127== searching for pointers to 1 not-freed blocks.
上述信息表明存在内存泄漏。修改程序后再次执行:
valgrind -v --tool=memcheck --leak-check=full ./mytest
valgrind打印的信息摘录如下:
==3155== malloc/free: in use at exit: 0 bytes in 0 blocks.
==3155== malloc/free: 4 allocs, 4 frees, 480 bytes allocated.
==3155==
==3155== All heap blocks were freed -- no leaks are possible.
上述信息表明已经没有内存泄漏了。
第三种方法使用mtrace:
首先有如下用于实验的程序代码,main.cpp:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <mcheck.h>
using namespace std;
int main()
{
mtrace();
char *p = (char *)malloc(128);
free(p);
p = (char *)calloc(256, 1);
free(p);
p = (char *)malloc(64);
//free(p);
p = new char [32];
delete [] p;
muntrace();
return 0;
}
编译:
g++ -g -W -Wall -Wextra -o mytest main.cpp
函数mtrace给内存分配函数安装handler,muntrace函数禁止这些handler。
这两个函数声明在mcheck.h文件中。mtrace会将环境变量MALLOC_TRACE指定
的文件截短为0,以便向该文件写入相关的内存信息。因此使用如下命令
执行程序:
env MALLOC_TRACE=./mcheck.txt ./mytest
调用muntrace函数之后,程序会将内存的动态分配信息写入
环境变量MALLOC_TRACE指定的文件,这个例子生成的是
名为mcheck.txt的文件。之后可以通过查看该文件的内容
来检测是否存在内存泄漏:
(不同的计算机生成的文件内容可能是不同的)
= Start
@ ./mytest:[0x80486ae] + 0x8ba0378 0x80
@ ./mytest:[0x80486be] - 0x8ba0378
@ ./mytest:[0x80486d2] + 0x8ba0378 0x100
@ ./mytest:[0x80486e2] - 0x8ba0378
@ ./mytest:[0x80486ee] + 0x8ba0378 0x40
@ /usr/lib/libstdc++.so.6:(_Znwj+0x27)[0x6cceb27] + 0x8ba03c0 0x20
@ /usr/lib/libstdc++.so.6:(_ZdlPv+0x21)[0x6ccc681] - 0x8ba03c0
= End
从文件中可以看到内存分配的地址和空间大小,以及内存的分配和释放的次数。
加号代表分配,减号代表释放。有四个加号,而减号只有三个,说明有内存泄漏发生。
修改上面源代码的第24行,再次编译执行,mcheck.txt的内容变为:
= Start
@ ./mytest:[0x80486ae] + 0x9765378 0x80
@ ./mytest:[0x80486be] - 0x9765378
@ ./mytest:[0x80486d2] + 0x9765378 0x100
@ ./mytest:[0x80486e2] - 0x9765378
@ ./mytest:[0x80486ee] + 0x9765378 0x40
@ ./mytest:[0x80486fe] - 0x9765378
@ /usr/lib/libstdc++.so.6:(_Znwj+0x27)[0x6cceb27] + 0x97653c0 0x20
@ /usr/lib/libstdc++.so.6:(_ZdlPv+0x21)[0x6ccc681] - 0x97653c0
= End
没有内存泄漏了。
参考文献:
mtrace(3), malloc_hook(3)
内存泄漏检测
最新推荐文章于 2024-07-25 19:56:10 发布