内存泄漏检查方法(for Linux)
如果你更想读原始文档, 请参考glibc info的"Allocation Debugging"一章 (执行info libc);
glibc提供了一个检查内存泄漏的方法, 前提是你的程序使用glibc的标准函数分配内存(如malloc, alloc...):
1. 在需要内存泄漏检查的代码的开始调用void mtrace(void) (在mcheck.h中有声明). mtrace为malloc等函数安装hook, 用于记录内存分配信息.在需要内存泄漏检查的代码的结束调用void muntrace(void).
注意: 一般情况下不要调用muntrace, 而让程序自然结束. 因为可能有些释放内存的的代码要到muntrace之后才运行.
2. 用debug模式编译被检查代码(-g或-ggdb)
3. 设置环境变量MALLOC_TRACE为一文件名, 这一文件将存有内存分配信息.
4. 运行被检查程序, 直至结束或muntrace被调用.
5. 用mtrace命令解析内存分配Log文件($MALLOC_TRACE)
(mtrace foo $MALLOC_TRACE, where foo is the executible name)
如果有内存泄漏, mtrace会输出分配泄漏内存的代码位置,以及分配数量.
其他东西
1. 可以将mtrace, muntrace放入信号处理函数(USR1, USR2), 以动态地进行内存泄漏检查控制.
2. mtrace是个perl代码, 如果你对符号地址与代码文本的转换感兴趣, 可以读一下.
3. again, 尽量不要用muntrace()
For C++ Leak:
检查内存泄漏的方法除glibc提供外;
还可以试试一些专用的程序;如:
ccmalloc
http://www.inf.ethz.ch/personal/biere/projects/ccmalloc/ccmalloc-english.html
mpatrol
http://www.cbmamiga.demon.co.uk/mpatrol/
这俩个工具的功能相当不错,能对程序进行相当全面的检查
01 #include <stdlib.h>
02 #include <mcheck.h>
--------------------------------------------
= End
--------------------------------------------
#include <stdlib.h>
#include <mcheck.h>
void func(void)
{
int* ptr = malloc(10 * sizeof(int));
//free(ptr);
}
int main(void)
{
setenv("MALLOC_TRACE", "output_file_name", 1);
mtrace();
func();
while (1)
{
sleep (1);
func ();
muntrace();
}
return 0;
}
= Start
@ ./a.out:[0x8048456] + 0x804a468 0x28
@ ./a.out:[0x8048456] + 0x804a498 0x28
= End
虽然while中反复调用func()但是此处只检测到两次(while外一次,while内一次)
---------------------------------------------
#include <stdlib.h>
#include <mcheck.h>
void func(void)
{
int* ptr = malloc(10 * sizeof(int));
//free(ptr);
}
int main(void)
{
setenv("MALLOC_TRACE", "output_file_name", 1);
mtrace();
func();
while (1)
{
sleep (1);
func ();
//muntrace();
}
return 0;
}
这种使用方式,进程中守护任务,所以output_file_name不会马上有内存,需要等一会儿
函数各自生成自己的内存泄露检测报告,这样比较麻烦
---------------------------------------------
#include <stdlib.h>
#include <mcheck.h>
#include <stdio.h>
void func(void)
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
int* ptr = malloc(10 * sizeof(int));
//free(ptr);
muntrace();
}
void test()
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
int* ptr = malloc(10 * sizeof(int));
//free(ptr);
muntrace();
}
void task()
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
int* ptr = malloc(10 * sizeof(int));
//free(ptr);
while (1)
{
usleep (10);
/* 如果不在这里调用muntrace,将不能生成检测报告 */
muntrace();
}
}
int main(void)
{
//mtrace();
func();
test();
task();
return 0;
}
普通函数统一报告,有无限循环的函数单独生成报告
---------------------------------------------
#include <stdlib.h>
#include <mcheck.h>
#include <stdio.h>
void func(void)
{
int* ptr = malloc(10 * sizeof(int));
}
void test()
{
int* ptr = malloc(10 * sizeof(int));
}
void task()
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
int* ptr = malloc(10 * sizeof(int));
while (1)
{
usleep (10);
/* 如果不在这里调用muntrace,将不能生成检测报告 */
muntrace();
}
}
int main(void)
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
func();
test();
task();
return 0;
}
创建线程前检测一次,并结束检测;线程自行检测;线程创建后不能再进行检测,
如果需要检测,则不能调用muntrace(),但是检测还是会失效
---------------------------------------------
#include <stdlib.h>
#include <mcheck.h>
#include <stdio.h>
#include <pthread.h>
void func(void)
{
int* ptr = malloc(10 * sizeof(int));
}
void test()
{
int* ptr = malloc(100 * sizeof(int));
}
void task()
{
char buff[128];
snprintf (buff, sizeof (buff), "%s", __FUNCTION__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
int* ptr = malloc(1000 * sizeof(int));
while (1)
{
usleep (10);
/* 如果不在这里调用muntrace,将不能生成检测报告 */
muntrace();
}
}
int main(void)
{
pthread_t id;
int i, ret;
char buff[128];
snprintf (buff, sizeof (buff), "%s%d", __FUNCTION__, __LINE__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
func();
test();
muntrace();
ret = pthread_create(&id, NULL, (void *)task, NULL);
if (ret != 0)
{
printf("Create pthread error!\n");
exit(1);
}
#if 0 /* 创建线程(线程自行负责检测)后,就不能再检测了,否则会有段错误 */
snprintf (buff, sizeof (buff), "%s%d", __FUNCTION__, __LINE__);
setenv("MALLOC_TRACE", buff, 1);
mtrace();
test();
//muntrace();
#endif
sleep(1);
//while (1) {}
return 0;
}