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;所有的堆空間都被釋放,沒有記憶體洩露。
【完】
相關文章
- 記憶體洩漏定位工具之 valgrind 使用記憶體
- valgrind 記憶體洩漏分析記憶體
- java中如何檢視記憶體洩露Java記憶體洩露
- 聊一聊 Valgrind 監視非託管記憶體洩露和崩潰記憶體洩露
- 線上記憶體洩露定位--memleak工具記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- SHBrowseForFolder 記憶體洩露記憶體洩露
- iOS檢測記憶體洩漏iOS記憶體
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- C/C++程式除錯和記憶體檢測C++除錯記憶體
- C++--問題27--如何檢測記憶體洩漏C++記憶體
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- C/C++應用程式記憶體洩漏檢查統計方案C++記憶體
- ArkTS 的記憶體快照與記憶體洩露除錯記憶體洩露除錯
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- 如何在 Linux 下檢測記憶體洩漏Linux記憶體
- C語言記憶體洩露很嚴重,如何應對?C語言記憶體洩露
- Android 記憶體洩漏檢測工具 LeakCanary(Kotlin版)的實現原理Android記憶體Kotlin
- win10驅動記憶體洩露如何解決_win10記憶體洩露處理方法Win10記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- android Handler導致的記憶體洩露Android記憶體洩露
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- 乾貨分享:淺談記憶體洩露記憶體洩露
- 解決git記憶體洩露問題Git記憶體洩露
- Android記憶體洩漏檢測與修復技巧Android記憶體
- php常駐程式記憶體洩露的簡單解決PHP記憶體洩露
- 記一次"記憶體洩露"排查過程記憶體洩露
- 使用VLD進行記憶體洩漏檢測(release + debug)記憶體
- Python實現記憶體洩露排查的示例Python記憶體洩露
- Android效能最佳化之記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- 簡單的記憶體“洩露”和“溢位”記憶體
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露