Linux下的Valgrind真是利器啊(不知道Valgrind的請自覺查看參考文獻(1)(2)),幫我找出了不少C++中的記憶體管理錯誤,前一陣子還在糾結為什麼VS 2013下運行良好的程式到了Linux下用g++編譯運行卻崩潰了,給出一堆彙編代碼也看不懂。久久不得解過後,想想肯定是記憶體方面的錯誤,VS在這方面一般都不檢查的,就算你的程式千瘡百孔,各種記憶體泄露、記憶體管理錯誤,只要不影響運行,沒有讀到不該讀的東西VS就不會告訴你(應該是VS內部沒實現這個記憶體檢測功能),因此用VS寫出的程式可能不是完美或健壯的。
更新:感謝部落格園好心網友@shines77的熱心推薦,即VS中有記憶體流失偵查工具外掛程式VLD(Visual Leak Detector),需要下載安裝,安裝方法請看官方介紹,使用非常簡單,在第一個入口檔案裡加上#include <vld.h>就可以了,檢測報告在輸出視窗中。我安裝使用了下,不知道是安裝錯誤還是什麼,無論程式有無記憶體泄露,輸出都是“No memory leaks detected.”
下面是我通過 Valgrind第一次檢測得到的結果和一點點修改後得到的結果(還沒改完,所以還有不少記憶體泄露問題……):
第一次檢測結果:慘不忍睹,因為程式規模有些大。
根據提示一點點修改過後,雖然還有個別錯誤和記憶體泄露問題,但還在修改中,至少已經能成功運行了……
真感謝Valgrind幫我成功找出了一堆記憶體問題,尋找過程中也為自己犯的低級錯誤而感到羞愧,所以記錄下來以便謹記。
1. 最多最低級的錯誤:不匹配地使用malloc/new/new[] 和 free/delete/delete[]
這樣的錯誤主要源於我對C++的new/new[]、delete/delete[]機制不熟悉,凡是new/new[]分配記憶體的類型變數我一概用delete進行釋放,或者有的變數用malloc進行分配,結果釋放的時候卻用delete,導致申請、釋放很多地方不匹配,很多記憶體空間沒能釋放掉。為了維護方便,我後來一律使用new/new[]和delete/delete[],拋棄C中的malloc和free。
如果將使用者new的類型分為基礎資料型別 (Elementary Data Type)和自訂資料類型兩種,那麼對於下面的操作相信大家都很熟悉,也沒有任何問題。
(1)基礎資料型別 (Elementary Data Type)
一維指標:
// 申請空間int *d = new int[5]; // 釋放空間delete[] d;
二維指標:
// 申請空間int **d = new int*[5];for (int i = 0; i < 5; i++) d[i] = new int[10]; // 釋放空間for (int i = 0; i < 5; i++) delete[] d[i];delete[] d;