linux下內存泄露檢測工具Valgrind

日前在linux開發一個分析實時路況的應用程序,在聯合測試中發現程序存在內存泄露的情況。

這下着急了,馬上就要上線了,還好發現了一款Valgrind工具,完美的解決了內存泄露的問題。

推薦大家可以使用看看。

 

Valgrind是運行在Linux上一套基於仿真技術的程序調試和分析工具,它的主要作者是獲得過Google-O'Reilly開源大獎的Julian Seward,它包含一個內核──一個軟件合成的CPU,和一系列的小工具,每個工具都可以完成一項任務──調試,分析,或測試等。Valgrind可以檢測內存泄漏和內存違例,還可以分析cache的使用等,靈活輕巧而又強大,能直穿程序錯誤的心臟,真可謂是程序員的瑞士軍刀。 

(一). Valgrind概觀 
Valgrind一般包含下列工具: 
1.Memcheck (後續我們只對這款內存檢測工具做介紹)
最常用的工具,用來檢測程序中出現的內存問題,所有對內存的讀寫都會被檢測到,一切對malloc()/free()/new/delete的調用都會被捕獲。所以,它能檢測以下問題: 
1.對未初始化內存的使用; 
2./寫釋放後的內存塊; 
3./寫超出malloc分配的內存塊; 
4./寫不適當的棧中內存塊; 
5.內存泄漏,指向一塊內存的指針永遠丟失; 
6.不正確的malloc/freenew/delete匹配; 
7,memcpy()相關函數中的dstsrc指針重疊。 
這些問題往往是C/C++程序員最頭疼的問題,Memcheck在這裏幫上了大忙。 
2.Callgrind 
gprof類似的分析工具,但它對程序的運行觀察更是入微,能給我們提供更多的信息。和gprof不同,它不需要在編譯源代碼時附加特殊選項,但加上調試選項是推薦的。Callgrind收集程序運行時的一些數據,建立函數調用關係圖,還可以有選擇地進行cache模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate可以把這個文件的內容轉化成可讀的形式。 
3.Cachegrind 
Cache分析器,它模擬CPU中的一級緩存I1Dl和二級緩存,能夠精確地指出程序中cache的丟失和命中。如果需要,它還能夠爲我們提供cache丟失次數,內存引用次數,以及每行代碼,每個函數,每個模塊,整個程序產生的指令數。這對優化程序有很大的幫助。 
4.Helgrind 
它主要用來檢查多線程程序中出現的競爭問題。Helgrind尋找內存中被多個線程訪問,而又沒有一貫加鎖的區域,這些區域往往是線程之間失去同步的地方,而且會導致難以發掘的錯誤。Helgrind實現了名爲“Eraser”的競爭檢測算法,並做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處於實驗階段。 
5. Massif 
堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少內存的使用,在帶有虛擬內存的現代系統中,它還能夠加速我們程序的運行,減少程序停留在交換區中的機率。 
此外,lackeynulgrind也會提供。Lackey是小型工具,很少用到;Nulgrind只是爲開發者展示如何創建一個工具。我們就不做介紹了。 

 

(二). Valgrind下載與安裝

1、下載:

valgrind官網:http://valgrind.org下載

如果安裝有svn則可以直接下載最新版本:svn co svn://svn.valgrind.org/valgrind/trunk valgrind

2、安裝

cd valgrind

 ./autogen.sh

./configure --prefix=...

make

make install

 

(二). 使用Memcheck 工具進行內存分析

1、編譯你的程序debug版本./TestMem

2、執行:valgrind --tool=memcheck --leak-check=full --log-file=./log.txt  ./TestMem

3、耐心等待並分析結果(log.txt結果文件中會包含引起內存泄露的代碼在在源碼中的位置,即以下舉例說明中標明爲紅色的部分)

舉例說明:

下面是一段有問題的C程序代碼test.c

#include <stdlib.h>
void f(void)
{
int* x = malloc(10 * sizeof(int));
x[10] = 0; //問題1: 數組下標越界
} //問題2: 內存沒有釋放
int main(void)
{
f();
return 0;
}
1、 編譯程序test.c
gcc -Wall test.c -g -o test
2、 使用Valgrind檢查程序BUG
valgrind --tool=memcheck --leak-check=full ./test
3、 分析輸出的調試信息
==3908== Memcheck, a memory error detector.
==3908== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==3908== Using LibVEX rev 1732, a library for dynamic binary translation.
==3908== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==3908== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==3908== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==3908== For more details, rerun with: -v
==3908== 
--3908-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--3908-- DWARF2 CFI reader: unhandled CFI instruction 0:50
/*數組越界錯誤*/
==3908== Invalid write of size 4 
==3908== at 0x8048384: f (test.c:6)
==3908== by 0x80483AC: main (test.c:11)
==3908== Address 0x400C050 is 0 bytes after a block of size 40 alloc'd
==3908== at 0x40046F2: malloc (vg_replace_malloc.c:149)
==3908== by 0x8048377: f (test.c:5)
==3908== by 0x80483AC: main (test.c:11)
==3908== 
==3908== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 14 from 1)
==3908== malloc/free: in use at exit: 40 bytes in 1 blocks. 
==3908== malloc/free: 1 allocs, 0 frees, 40 bytes allocated.
==3908== For counts of detected errors, rerun with: -v
==3908== searching for pointers to 1 not-freed blocks.
==3908== checked 59,124 bytes.
==3908== 
==3908== 
/*有內存空間沒有釋放*/
==3908== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3908== at 0x40046F2: malloc (vg_replace_malloc.c:149)
==3908== by 0x8048377: f (test.c:5)
==3908== by 0x80483AC: main (test.c:11)
==3908== 
==3908== LEAK SUMMARY:
==3908== definitely lost: 40 bytes in 1 blocks.
==3908== possibly lost: 0 bytes in 0 blocks.
==3908== still reachable: 0 bytes in 0 blocks.
==3908== suppressed: 0 bytes in 0 blocks.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章