1. 程式人生 > >linux下用valgrind檢查程式記憶體洩漏

linux下用valgrind檢查程式記憶體洩漏

2010-12-27

http://abloz.com 2010.12.27

問題提出: 如果一個較複雜的程式,有記憶體洩漏,如何檢測? 在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 0x400512: f (testmem.c:6)
==14783==    by 0x400522: 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 0x400505: f (testmem.c:5)
==14783==    by 0x400522: 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 0x400505: f (testmem.c:5)
==14783==    by 0x400522: 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 0x400505: 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

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源