天天看点

linux下用valgrind检查程序内存泄漏 问题提出:

问题提出:

如果一个较复杂的程序,有内存泄漏,如何检测?

在windows下,VC本身带有内存泄漏的检查,程序结束时输出窗口会提示有多少memory leaks. linux下有什么办法呢?

1.发现内存泄漏,可以用top或ps。

[email protected]:~/smscore$ top | grep firefox

会持续打印firefox的内存占用状况,可以重定向到文件中。

2.静态检测

用splint, PC-LINT,IBM的 BEAM(IBM Checking Tool for Bugs Errors and Mistakes)等。在本文略过。

3.动态检测

有IBM的rational purify,开源的valgrind. 本文主要介绍valgrind。

Valgrind 现在提供多个工具,其中最重要的是 Memcheck,Cachegrind,Massif 和 Callgrind。Valgrind 是在 Linux 系统下开发应用程序时用于调试内存问题的工具。它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。其中的 memecheck 工具可以用来寻找 c、c++ 程序中内存管理的错误。可以检查出下列几种内存操作上的错误:

* 读写已经释放的内存

* 读写内存块越界(从前或者从后)

* 使用还未初始化的变量

* 将无意义的参数传递给系统调用

* 内存泄漏

valgrind网址:http://valgrind.org/。到现在为止最新版:3.60,支持ubuntu 10.10.对centos 5.2可以直接编译安装使用,ubuntu中遇到一些问题。

3.1下载

[email protected]:~/valgrind$ wget http://valgrind.org/downloads/valgrind-3.6.0.tar.bz2

我开始用较老的版本,configure时遇到glibc版本太新的问题。

[email protected]:~/valgrind/valgrind-3.4.1$ ./configure

checking the GLIBC_VERSION version… unsupported version

configure: error: Valgrind requires glibc version 2.2 – 2.10

我的系统环境:

[email protected]:~$ uname -a

Linux zhh64 2.6.35-24-generic #42-Ubuntu SMP Thu Dec 2 02:41:37 UTC 2010 x86_64 GNU/Linux

[email protected]:~$ cat /etc/lsb-release

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=10.10

DISTRIB_CODENAME=maverick

DISTRIB_DESCRIPTION=”Ubuntu 10.10″

[email protected]:~$ ls -l /lib/libc.so.6

lrwxrwxrwx 1 root root 14 2010-11-22 09:58 /lib/libc.so.6 -> libc-2.12.1.so

[email protected]:~$ ls /lib/libc*

/lib/libc-2.12.1.so

[email protected]:~$ /lib/libc.so.6

GNU C Library (Ubuntu EGLIBC 2.12.1-0ubuntu10) stable release version 2.12.1, by Roland McGrath et al.

[email protected]:~$ gcc -v

Using built-in specs.

Target: x86_64-linux-gnu

gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)

下载完成后,解压tar xvf valgrind-3.6.0.tar.bz2,然后configure,编译安装,都没有问题。

[email protected]:~/valgrind/valgrind-3.6.0$ ./configure

[email protected]:~/valgrind/valgrind-3.6.0$ make

[email protected]:~/valgrind/valgrind-3.6.0$ sudo make install

3.2执行检测

[email protected]:~/test$ valgrind –leak-check=yes ./bin/myprog

valgrind: Fatal error at startup: a function redirection

valgrind: which is mandatory for this platform-tool combination

valgrind: cannot be set up. Details of the redirection are:

valgrind:

valgrind: A must-be-redirected function

valgrind: whose name matches the pattern: strlen

valgrind: in an object with soname matching: ld-linux-x86-64.so.2

valgrind: was not found whilst processing

valgrind: symbols from the object with soname: ld-linux-x86-64.so.2

valgrind:

valgrind: Possible fixes: (1, short term): install glibc’s debuginfo

valgrind: package on this machine. (2, longer term): ask the packagers

valgrind: for your Linux distribution to please in future ship a non-

valgrind: stripped ld.so (or whatever the dynamic linker .so is called)

valgrind: that exports the above-named function using the standard

valgrind: calling conventions for this platform.

valgrind:

valgrind: Cannot continue — exiting now. Sorry.

发现程序中使用了strlen,valgrind就直接退出了。原因是glibc没有debuginfo.

安装glibc的debug info:

[email protected]:~$ sudo apt-cache search libc6-dbg

libc6-dbg – Embedded GNU C Library: detached debugging symbols

libc6-dbg-armel-cross – Embedded GNU C Library: detached debugging symbols (for cross-compiling)

[email protected]:~$ sudo apt-get install libc6-dbg

再执行,程序结束时,就会有内存泄漏的提示了。

4.测试

vi testmem.c

#include <stdlib.h>   void f(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun } // problem 2: memory leak -- x not freed   int main(void) { f(); return 0; }      

编译:

[email protected]:~/test$ gcc -g -O0 -o testmem testmem.c

执行:

[email protected]:~/test$ valgrind –leak-check=yes testmem

valgrind: testmem: command not found

[email protected]:~/test$ valgrind –leak-check=yes ./testmem

==14783== Memcheck, a memory error detector

==14783== Copyright (C) 2002-2010, and GNU GPL’d, by Julian Seward et al.

==14783== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info

==14783== Command: ./testmem

==14783==

==14783== Invalid write of size 4

==14783== at 0×400512: f (testmem.c:6)

==14783== by 0×400522: main (testmem.c:11)

==14783== Address 0x51b1068 is 0 bytes after a block of size 40 alloc’d

==14783== at 0x4C2827C: malloc (vg_replace_malloc.c:236)

==14783== by 0×400505: f (testmem.c:5)

==14783== by 0×400522: main (testmem.c:11)

==14783==

==14783==

==14783== HEAP SUMMARY:

==14783== in use at exit: 40 bytes in 1 blocks

==14783== total heap usage: 1 allocs, 0 frees, 40 bytes allocated

==14783==

==14783== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1

==14783== at 0x4C2827C: malloc (vg_replace_malloc.c:236)

==14783== by 0×400505: f (testmem.c:5)

==14783== by 0×400522: main (testmem.c:11)

==14783==

==14783== LEAK SUMMARY:

==14783== definitely lost: 40 bytes in 1 blocks

==14783== indirectly lost: 0 bytes in 0 blocks

==14783== possibly lost: 0 bytes in 0 blocks

==14783== still reachable: 0 bytes in 0 blocks

==14783== suppressed: 0 bytes in 0 blocks

==14783==

==14783== For counts of detected and suppressed errors, rerun with: -v

==14783== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)

可以看到,40 bytes in 1 blocks are definitely lost in loss record 1 of 1

by 0×400505: f (testmem.c:5)

所以testmem.c第5行有40byte的泄漏。

查看源码,int* x = malloc(10 * sizeof(int));分配的内存没有释放。

其中,–leak-check=yes表示检测内存。

如果程序原来执行命令是

myprog var1 var2

则用valgrind检测的执行命令是

valgrind –leak-check=yes myprog var1 var2

程序gcc的编译选项必须带-g, 最好带-O0,表示没有优化,方便定位问题。

5.参考

http://valgrind.org/docs/manual/quick-start.html

http://www.ibm.com/developerworks/cn/linux/l-cn-memleak/index.html

http://fafeng.blogbus.com/logs/7525571.html