2010-11-28 57 views
0

在編譯時有沒有在gcc中啓用內存管理的選項?使用Valgrind的調試時使用GCC編譯的C代碼在gcc中不啓用內存管理

+1

請您解釋一下「無內存管理」是什麼意思?還有它應該應用於什麼? GCC?它的輸出? – thkala 2010-11-28 16:11:03

回答

11

要點:

  • 使用-O0編譯代碼。在一些比較罕見的情況下(例如內聯彙編),您可能需要-O1。 永不使用更高的優化級別。編譯器會嚴重破壞你的代碼,以至於它可能使你的生活變得不可能。變量可以完全消失,函數可以在內聯時離開,循環展開等等。基本上,除-O以外的任何其他內容都會帶來可執行代碼與您的源代碼幾乎不相似的風險。

  • 使用-g GCC選項可以將調試符號添加到代碼中,並且不會去除可執行文件。就像任何其他調試器一樣,valgrind將使用可用的調試符號生成無限多的有用輸出。他們將幫助valgrind將內存地址匹配到代碼中的特定文件和行號,這是非常寶貴的。

要跟蹤內存泄漏和許多其他問題,我建議與運行您的程序:

valgrind --log-file=valgrind.log --leak-check=full --track-origins=yes --show-reachable=yes ./program 

然後看看在發現任何問題valgrind.log文件。

編輯:

關於Valgrind的選擇,我建議:

  • --log文件=告訴的valgrind發送其輸出到一個文件,我相信可以使事情,當你更容易調試程序並將其輸出到控制檯,或發現許多問題時。

  • --leak-check = full告訴valgrind告訴你有關每個泄漏內存塊的詳細信息。

  • --track-origins = yes告訴valgrind找出未初始化值來自哪裏。它與內存泄漏沒有任何關係,儘管它可以幫助處理其他問題。不過,它會讓你的程序變得更慢,所以你可能想要刪除這個選項並且只在追蹤未初始化的值的時候添加它。

  • --show-reachable = yes告訴valgrind輸出已分配但未釋放的內存塊,即使在程序退出時仍有指向它們的指針。這些塊不是技術上丟失/泄漏,因爲你仍然有指向它們的指針。儘管如此,他們仍然可以a)指出程序中存在邏輯問題(例如列表無限增長)b)如果您的main()集成爲另一個更大程序中的函數,它們可以並將成爲內存泄漏。最好不要留下這樣的問題。

  • 有一個--track-fds = yes選項,可以幫助找到泄漏的文件描述符而不僅僅是內存。

有些程序員主張禁止在程序結束時釋放內存或關閉文件描述符,因爲操作系統無論如何都會這樣做。雖然那裏有一個性能和代碼大小的優勢,恕我直言,這應該只由有經驗的程序員完成,並且它應該由刪除生產版本的代碼,而不是從不寫它。否則,這會鼓勵不應該允許的錯誤編碼做法。

編輯2:

一個重要的提示:如果Valgrind的指示代碼中的問題,這是最可能是正確的,即使你的程序不會崩潰。取決於結構對齊,內存分配器行爲,平臺,編譯器版本和標誌,或者月亮的相位,一些「次要」錯誤(例如,讀取緩衝區末尾的一個字節)可能不會被看到。如果您更改編譯器,libc,平臺或位(例如,從64位變爲32位),帶有這些問題的代碼可能會中斷。

1

無需優化即可編譯您的程序,並使用調試符號獲得最佳結果(-O0 -g)。

現在運行您的程序的一個實例,利用盡可能多的功能越好,包裝通話就像這樣:

valgrind ./myprog my prog args 

我常常覺得有用通過以下標誌的valgrind:

valgrind --leak-check=full --track-fds=yes --track-origins=yes --malloc-fill=0x80 --free-fill=0x7f ./myprog my prog args 

然而,valgrind會提供很多提示,幫助您瞭解通過哪些參數,是否應該在不太全面的通行證上找到相關內容。