Linux C内存泄露检测工具

内存泄漏检查方法(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>
03 
04 void func(void)
05 {
06     int* ptr = malloc(10 * sizeof(int));
07     //free(ptr);          
08 }
09 
10 int main(void)
11 {
12     setenv("MALLOC_TRACE", "output_file_name", 1);
13     mtrace();
14     func();
15     return 0;
16 }

# gcc test.c -o test -g
# ./test
# more  output_file_name 
= Start
@ ./test:[0x80483e6] + 0x804a470 0x28
@ /lib/tls/i686/cmov/libc.so.6:(clearenv+0x7c)[0xb7e449ac] - 0x804a008
@ /lib/tls/i686/cmov/libc.so.6:(tdestroy+0x47)[0xb7eec6d7] - 0x804a0c0
@ /lib/tls/i686/cmov/libc.so.6:(tdestroy+0x4f)[0xb7eec6df] - 0x804a0e8

# mtrace output_file_name
- 0x0804a008 Free 3 was never alloc'd 0xb7e449ac
- 0x0804a0c0 Free 4 was never alloc'd 0xb7eec6d7
- 0x0804a0e8 Free 5 was never alloc'd 0xb7eec6df

Memory not freed:
-----------------
0  Address     Size     Caller
0x0804a470     0x28  at 0x80483e6







01 #include <stdlib.h>
02 #include <mcheck.h>
03 
04 void func(void)
05 {
06     int* ptr = malloc(10 * sizeof(int));
07     free(ptr);          
08 }
09 
10 int main(void)
11 {
12     setenv("MALLOC_TRACE", "output_file_name", 1);
13     mtrace();
14     func();
15     return 0;
16 }


# more  output_file_name 
= Start
@ ./test:[0x8048426] + 0x804a470 0x28
@ ./test:[0x8048434] - 0x804a470
@ /lib/tls/i686/cmov/libc.so.6:(clearenv+0x7c)[0xb7e149ac] - 0x804a008
@ /lib/tls/i686/cmov/libc.so.6:(tdestroy+0x47)[0xb7ebc6d7] - 0x804a0c0
@ /lib/tls/i686/cmov/libc.so.6:(tdestroy+0x4f)[0xb7ebc6df] - 0x804a0e8 

0x8048426 分配内存空间的指令地址
0x804a470 malloc分配的内存空间己地址
+         表示分配内存
-         表示释放内存


# mtrace output_file_name 
- 0x0804a008 Free 4 was never alloc'd 0xb7e149ac
- 0x0804a0c0 Free 5 was never alloc'd 0xb7ebc6d7
- 0x0804a0e8 Free 6 was never alloc'd 0xb7ebc6df
No memory leaks.




 

 

--------------------------------------------
#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)
    {
        muntrace();
    }
    return 0;
}


$ ./a.out &
$ more output_file_name 
= Start
@ ./a.out:[0x8048426] + 0x804a468 0x28

= 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值