有两种比较好的方法跟踪由于malloc后未free造成的内存泄漏:
一、mtrace工具
mtrace是一个有效的工具来查看有没有内存泄漏。它会将内存出现的异常记录在日志中,而日志的路径是可以指定的。
-
#include<stdio.h>
-
#include<stdlib.h>
-
#include<mcheck.h>
-
#include<assert.h>
-
-
int main(void)
-
{
-
assert(!setenv("MALLOC_TRACE","./malloc.log",1)) ;
-
mtrace();
-
-
int *p = malloc(100*sizeof(int));
-
-
return 0;
-
}
我们看上面的代码,mtrace打开跟踪开关,我们malloc了400个字节的内存空间,但是我们并没有调用free将malloc出来的空间释放掉(当然函数退出也就释放了,但是这种释放不太优雅)。
mtrace会将内存情况记录下来,记录的结果存在什么地方呢?由环境变量MALLOC_TRACE决定。所以实际上有两种设置环境变量的方法,一种情况就是代码中体现的:
1、setenv函数设定环境变量 MALLOC_TRACE
setenv("MALLOC_TRACE","./malloc.log",1)
2、shell设定环境变量MALLOC_TRACE
export MALLOC_TRACE=~/program/C/MEM_CHECK/memcheck.log
下面是输出情况:
-
root@libin:~/program/C/mem_bug# gcc -o test test.c -g
-
root@libin:~/program/C/mem_bug# ./test
-
root@libin:~/program/C/mem_bug# ll
-
总用量 28
-
drwxr-xr-x 2 root root 4096 2012-04-03 12:17 ./
-
drwxr-xr-x 36 root root 4096 2012-04-03 12:01 ../
-
-rw-r--r-- 1 root root 155 2012-04-03 12:17 malloc.log
-
-rwxr-xr-x 1 root root 8550 2012-04-03 12:17 test*
-
-rw-r--r-- 1 root root 208 2012-04-03 12:17 test.c
-
root@libin:~/program/C/mem_bug# mtrace ./test malloc.log
-
- 0x09a68008 Free 3 was never alloc'd 0x1da8ef
-
- 0x09a68028 Free 4 was never alloc'd 0x1da8f7
-
-
Memory not freed:
-
-----------------
-
Address Size Caller
-
0x09a683b0 0x190 at /home/libin/program/C/mem_bug/test.c:11
二、MALLOC_CHECK_宏
除了mtrace工具之外,MALLOC_CHECK_也是个不错的工具。
-
#include<stdio.h>
-
#include<stdlib.h>
-
-
int free_inside(int * p)
-
{
-
if(p)
-
free(p);
-
}
-
-
int main(oid)
-
{
-
int *p = malloc(100*sizeof(int));
-
-
-
free_inside(p);
-
free(p);
-
return 0;
-
}
我们可以看到,p指向的内存被释放了两次,第二次释放一定会出问题。
-
root@libin:~/program/C/mem_bug# env MALLOC_CHECK_=1 ./test
-
*** glibc detected *** ./test: free(): invalid pointer: 0x08d22008 ***
-
root@libin:~/program/C/mem_bug# ./test
-
*** glibc detected *** ./test: double free or corruption (top): 0x0943e008 ***
-
======= Backtrace: =========
-
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0xba4591]
-
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0xba5de8]
-
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xba8ecd]
-
./test[0x804845e]
-
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb4fbd6]
-
./test[0x8048381]
-
======= Memory map: ========
-
00526000-00541000 r-xp 00000000 08:0a 532971 /lib/ld-2.11.1.so
-
00541000-00542000 r--p 0001a000 08:0a 532971 /lib/ld-2.11.1.so
-
00542000-00543000 rw-p 0001b000 08:0a 532971 /lib/ld-2.11.1.so
-
0060e000-0060f000 r-xp 00000000 00:00 0 [vdso]
-
00b39000-00c8c000 r-xp 00000000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
-
00c8c000-00c8d000 ---p 00153000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
-
00c8d000-00c8f000 r--p 00153000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
-
00c8f000-00c90000 rw-p 00155000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
-
00c90000-00c93000 rw-p 00000000 00:00 0
-
00eed000-00f0a000 r-xp 00000000 08:0a 524925 /lib/libgcc_s.so.1
-
00f0a000-00f0b000 r--p 0001c000 08:0a 524925 /lib/libgcc_s.so.1
-
00f0b000-00f0c000 rw-p 0001d000 08:0a 524925 /lib/libgcc_s.so.1
-
08048000-08049000 r-xp 00000000 08:0b 1052377 /home/libin/program/C/mem_bug/test
-
08049000-0804a000 r--p 00000000 08:0b 1052377 /home/libin/program/C/mem_bug/test
-
0804a000-0804b000 rw-p 00001000 08:0b 1052377 /home/libin/program/C/mem_bug/test
-
0943e000-0945f000 rw-p 00000000 00:00 0 [heap]
-
b7700000-b7721000 rw-p 00000000 00:00 0
-
b7721000-b7800000 ---p 00000000 00:00 0
-
b78a5000-b78a6000 rw-p 00000000 00:00 0
-
b78bc000-b78be000 rw-p 00000000 00:00 0
-
bf917000-bf92c000 rw-p 00000000 00:00 0 [stack]
比较有用的信息是backtrace打印出来的堆栈调用关系,有了这个,我们就可以方便的利用objdump出来的汇编代码,定位问题,其中,报错很明白的告诉我们是double free,重复释放内存的问题。效果很好
*** glibc detected *** ./test: double free or corruption (top): 0x0943e008 ***
阅读(2334) | 评论(0) | 转发(0) |