Linux下記憶體問題檢測神器:Valgrind
阿新 • • 發佈:2019-07-27
在寫大型C/C++工程時難免會發生記憶體洩漏現象,系統程式設計中一個重要的方面就是有效地處理與記憶體相關的問題。你的工作越接近系統,你就需要面對越多的記憶體問題。有時這些問題非常瑣碎,而更多時候它會演變成一個除錯記憶體問題的惡夢。 常見的記憶體問題一共七種:1. 動態記憶體洩露;2. 資源洩露,比如檔案指標不關閉;3. 動態記憶體越界;4.陣列記憶體越界;5.動態記憶體double free;6.使用野指標,即未初始化的指標;7.釋放野指標,即未初始化的指標。 記憶體問題非常難定位,對於小工程來說,簡單去檢查程式碼中new和delete的匹配對數就基本能定位到問題,但是一旦程式碼量上升到以萬單位時,僅靠肉眼檢查來定位問題那就非常困難了,所以我們需要利用工具幫助我們找出問題所在。在Linux系統下記憶體檢測工具首推Valgrind,一款非常好用的開源記憶體管理框架。Valgrind其實是一個工具集,記憶體錯誤檢測只是它眾多功能的一個,但我們用得最多的功能正是它——memcheck。 該工具可以檢測下列與記憶體相關的問題 : 未釋放記憶體的使用 對釋放後記憶體的讀/寫 對已分配記憶體塊尾部的讀/寫 記憶體洩露 不匹配的使用malloc/new/new[] 和 free/delete/delete[] 重複釋放記憶體 首先安裝Valgrind非常簡單: //valgrind下載:http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2valgrind安裝:1. tar -jxvf valgrind-3.12.0.tar.bz22. cd valgrind-3.12.03. ./configure4. make5. sudo make install 下面開始講解Valgrind的應用場景。 注意: 下面討論的所有測試程式碼都應該使用gcc/g++並且加上-g選項。 1. 使用未初始化的記憶體(使用野指標) 這裡我們定義了一個指標p,但並未給他開闢空間,即他是一個野指標,但我們卻使用它了。 Valgrind檢測出我們程式使用了未初始化的變數,但並未檢測出記憶體洩漏。 2.在記憶體被釋放後進行讀/寫(使用野指標) p所指向的記憶體被釋放了,p變成了野指標,但是我們卻繼續使用這片記憶體。 Valgrind檢測出我們使用了已經free掉的記憶體,並給出這片記憶體是哪裡分配哪裡釋放的。 3.從已分配記憶體塊的尾部進行讀/寫(動態記憶體越界) 我們動態地分配了一段陣列,但我們在訪問個陣列時發生了越界讀寫,程式crash掉。 Valgrind檢測出越界的位置。 注意:Valgrind不檢查靜態分配陣列的使用情況!所以對靜態分配的陣列,Valgrind表示無能為力!比如下面的例子,程式crash掉,我們卻不知道為什麼。 4.記憶體洩漏 記憶體洩漏的原因在於沒有成對地使用malloc/free和new/delete,比如下面的例子。 Valgrind會給出程式中malloc和free的出現次數以判斷是否發生記憶體洩漏,比如對上面的程式執行memcheck,Valgrind的記錄顯示上面的程式用了1次malloc,卻呼叫了0次free,明顯發生了記憶體洩漏! 上面提示了我們可以使用--leak-check=full進一步獲取記憶體洩漏的資訊,比如malloc和free的具體行號。 5. 不匹配地使用malloc/new/new[] 和 free/delete/delete[] 正常使用new/delete和malloc/free是這樣子的: 而不匹配地使用malloc/new/new[] 和 free/delete/delete[]則會被提示mismacth: 6.兩次釋放記憶體 double free的情況同樣是根據malloc/free的匹配對數來體現的,比如free多了一次,Valgrind也會提示。 當然,Valgrind也不是萬能的。Valgrind也有無法找到問題的時候,有些問題只能通過不斷的review程式碼找到了癥結。發現問題,解決問題,畢竟是末流。最好的方法,就是不引入記憶體問題。這可以通過良好的程式碼風格和設計來實現的。 文末也給大家,分享主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK技術,面試技巧方面的資料技術討論。 感興趣的朋