C程式記憶體洩露檢測工具——Valgrind
緣起
C/C++程式設計師需要親力親為地管理記憶體,一不小心就會造成“記憶體洩露”。說到這兒,有的同學會問:記憶體洩露是什麼意思?
以下摘自 維基百科:
在電腦科學中,記憶體洩漏指由於疏忽或錯誤造成程式未能釋放已經不再使用的記憶體。記憶體洩漏並非指記憶體在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,導致在釋放該段記憶體之前就失去了對該段記憶體的控制,從而造成了記憶體的浪費。
除了在編碼時小心翼翼,還有什麼辦法能避免記憶體洩露呢?這裡為大家介紹一個工具——Valgrind. 它的官網是 http://valgrind.org/
正如官網所說:
Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. You can also use Valgrind to build new tools.
Valgrind 提供了許多除錯和分析工具,這些工具中最流行的稱為 Memcheck. 它可以檢測出許多在C/C ++程式中常見的與記憶體有關的錯誤。
Valgrind 的安裝
圖個省事,我們們就不從原始碼安裝了。
sudo apt install valgrind
這是一個沒有介面的記憶體檢測工具。安裝後,輸入valgrind ls -l
驗證一下該工具是否能用。(這是README裡面的方法,實際上是執行對ls -l
命令的記憶體檢測。)如果你看到類似下圖的資訊,說明安裝成功。
Valgrind 的使用
首先準備好原始碼,然後進行編譯。官網是這樣說的:
Compile your program with -g to include debugging information so that Memcheck’s error messages include exact line numbers. Using -O0 is also a good idea, if you can tolerate the slowdown. With -O1 line numbers in error messages can be inaccurate, although generally speaking running Memcheck on code compiled at -O1 works fairly well, and the speed improvement compared to running -O0 is quite significant. Use of -O2 and above is not recommended as Memcheck occasionally reports uninitialised-value errors which don’t really exist.
總之要加-g
選項,另外優化級別建議0或1級別,即加-O0
或者-O1
.
編譯後,假設生成的可執行檔案是a.out
,那麼請輸入
valgrind ./a.out
如果你的程式有命令列引數,那麼跟在後面就行。比如
valgrind ./a.out arg1 arg2
舉例
我的上一篇博文——堆的C語言實現——堆與堆排序(二)講了堆的初始化、構造、插入、刪除等,剛好用到了malloc
和free
函式,我們們就拿這個舉例。
只分配,不釋放
//測試函式
int main(void)
{
int a[]={4,1,3,2,16,9,10,14,8,7}; //10個
int elmt_cnt = sizeof(a) / sizeof(a[0]);
priority_queue pq1,pq2,pq3,pq4;
// 測試最大堆建構函式
pq1 = build_max_heap_bottom_up_recursive(a,elmt_cnt);
pq2 = build_max_heap_bottom_up(a,elmt_cnt);
pq3 = build_max_heap_up_bottom(a,elmt_cnt);
pq4 = build_max_heap_up_bottom2(a,elmt_cnt);
// 列印構造結果
print_heap(pq1);
print_heap(pq2);
print_heap(pq3);
print_heap(pq4);
// 測試刪除最大鍵的函式
int del_key = 0;
printf("delete the max key: ");
while(is_empty(pq3)==0) // 用pq3測試
{
del_key = delete_max(pq3);
printf("%d ", del_key);
}
printf("\n");
// destroy(pq1); //別忘了釋放記憶體!
// destroy(pq2);
// destroy(pq3);
// destroy(pq4);
return 0;
}
把後面的destroy
函式都註釋掉,編譯後用 Valgrind 工具檢測,結果如下圖。
Valgrind 報告顯示,在程式退出的時候,還有 240 位元組的記憶體在使用,也就是沒有釋放。
我們看看原始碼,這240位元組是怎麼來的?
不管用什麼方式構造堆,都會呼叫初始化函式:
struct heap_struct
{
int capacity;
int size;
element_t *elements;
};
...
priority_queue initialize(int capacity)
{
priority_queue heap;
...
heap = malloc( sizeof(struct heap_struct));
...
// +1 是因為要包含[0]
heap->elements = malloc( (capacity + 1) * sizeof(element_t) );
...
...
return heap;
}
我們計算一下這個初始化函式需要申請多少記憶體。結構體struct heap_struct
佔用的記憶體是 16(=4+4+8,我的系統是 x64 的 Ubuntu,指標佔8位元組)。heap->elements
指向的空間大小是44(=4*11)。所以共申請記憶體60(= 16+44)位元組。
在main
函式中構造了4個堆,所以共申請記憶體240(=60*4)位元組,這和檢測結果相符。
分配後正確釋放
加上main
函式最後的destroy(pq1)
等4條語句,編譯後再用 Valgrind 檢測,結果如下圖。
可以看出,程式退出時,還在使用的記憶體大小是0;所有的堆空間都被釋放,沒有記憶體洩露。
【完】
相關文章
- MLeaksFinder:精準 iOS 記憶體洩露檢測工具iOS記憶體洩露
- Android 檢測記憶體洩露Android記憶體洩露
- MFC記憶體洩露與檢測記憶體洩露
- LeakCanary 傻瓜式的記憶體洩露檢測工具記憶體洩露
- LeakCanary傻瓜式的記憶體洩露檢測工具記憶體洩露
- 記憶體洩漏定位工具之 valgrind 使用記憶體
- valgrind 記憶體洩漏分析記憶體
- 在iOS上自動檢測記憶體洩露iOS記憶體洩露
- C++ 程式記憶體洩漏檢測方法C++記憶體
- 【YFMemoryLeakDetector】人人都能理解的 iOS 記憶體洩露檢測工具類iOS記憶體洩露
- Android記憶體優化——記憶體洩露檢測分析方法Android優化記憶體洩露
- JavaScript記憶體洩漏檢測工具JavaScript記憶體
- C/C++記憶體洩漏及檢測C++記憶體
- linux下檢查記憶體洩露的工具--mtraceLinux記憶體洩露
- C++記憶體洩露檢查的5個方法C++記憶體洩露
- 記憶體洩露記憶體洩露
- 線上記憶體洩露定位--memleak工具記憶體洩露
- leaks工具查詢記憶體洩露記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- 聊一聊 Valgrind 監視非託管記憶體洩露和崩潰記憶體洩露
- 如何在vs下linux下檢測記憶體洩露Linux記憶體洩露
- js記憶體洩露JS記憶體洩露
- JavaScript記憶體洩露JavaScript記憶體洩露
- 記憶體洩露嗎記憶體洩露
- SHBrowseForFolder 記憶體洩露記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- iOS記憶體洩漏自動檢測工具PLeakSnifferiOS記憶體
- 使用新版Android Studio檢測記憶體洩露和效能Android記憶體洩露
- iOS檢測記憶體洩漏iOS記憶體
- 如何檢測記憶體洩漏記憶體
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- 記憶體洩露檢測工具 Visual Leak Detector for Visual C++ 2008/2010記憶體洩露C++
- Lowmemorykiller記憶體洩露分析記憶體洩露
- LeakCanary(二)記憶體洩露監測原理研究記憶體洩露
- vs2008下的MFC程式,怎麼檢測記憶體洩露C程式記憶體洩露
- malloc_stats---檢查記憶體洩露的神器記憶體洩露
- 檢視 Node.js 中的記憶體洩露Node.js記憶體洩露
- Android記憶體洩露分析以及工具的使用Android記憶體洩露