本文僅限記錄自己的一次 內存泄露追蹤小記。 可能並不十分適用與大家的情況。而且方法也並不是很smart。僅做記錄,能提供個思路更好。
一、 要問調試程序遇到什么問題最頭疼, 內存泄露肯定能排在前幾名里的。 內存泄露一般是由於 在申請、釋放內存的過程中,並沒有將其正確的結對使用。 出現了申請了內存,但是未釋放或者少釋放了內存的情況。 內存泄露問題的出現,可能短時間內不會造成很大的影響。但是如果長時間運行程序, 內存會被逐步蠶食殆盡。 而造成服務器(主機)工作異常的情況,嚴重的造成其他程序沒法正常工作,甚至宕機的情況。
二、遇到、發現內存泄露
內存泄露的問題,肯定不是一眼就看出來的。這個一般是長期觀察, 或者某種情況重復執行,並查看內存的使用情況,發現內存可用值逐步變少。而且停止該情況的執行后,內存使用率並不恢復。 此時, 出現內存泄露的問題的可能性就很大了。
三、找到內存泄露的必要條件
發現內存泄露了。最重要的是找到內存泄露的必要條件。最好是找到最一針見血的泄露條件。這個過程可能會比較長,如果情況較簡單的話還好說。 幾種條件試下來 基本上就能摸個差不多了! 但是如果碰到較復雜的情況,那么需要多鍾條件組合測試。 得出最根本的那個導致泄露的條件,成功就不遠了!
四、找到內存泄露的代碼
有了問題必現的條件, 那么接下來就得跟代碼了(廢話。。。)。 根據條件的處理過程一點點縷代碼, 查看內存的分配及釋放情況。查看是否有少釋放的情況。 不過這種方法是最笨的方法。
(1)介紹一個工具valgrind,雖然在我的debug 階段並未給予太大的幫助,而且還幫了點倒忙。但不妨礙要誇它是一款 很好的跟蹤內存問題的工具。
具體的使用方法可以參考 IBM 大神的文章 http://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/
說說它的優點:
不用向代碼里特意插入新的跟蹤代碼。 僅在編譯可執行程序時加入 -g 選項。 就可以使用valgrind 工具對其進行 內存調試啦。 方法還算簡單些。
但是有一點, 在我使用的程序中,是一個大循環。且是一個后台守護進程。 使用valgrind 就有點不方便了! 必現條件執行一次,非常之慢。。。 所以根據你的程序實際使用情況,甄別選用。如果沒有其他思路的時候,可以使用該工具跑一下,沒准就解決了呢!
(2) 笨辦法 在調用malloc/new, free/delete 等申請、釋放內存的函數處,打印申請過程和一些基本信息(申請空間的大小,地址,也可以使用一個全局變量記下申請、釋放的次數)。以便觀察哪塊有申請后,但沒有找到對應的釋放地方。
總結來講, 解決內存泄露沒有非常便捷的辦法。 預防方法就是規范自己的代碼編寫, 做好成對的申請與釋放。 在處理異常情況返回、退出時記得釋放之前申請的內存。養成編碼的好習慣。 或者架構軟件代碼時,可以將內存申請、釋放函數封裝一下, 增加自己的調試信息進去。多一些必要的調試信息對解決問題有很大的幫助。
出了內存泄露問題也不要太焦慮。沒法快速解決問題也不要着急。 如果不是那種一眼就看出來就有泄露的地方, 基本上花費的時間都不會短。所以保持自己debug的熱情,別氣餒。 一般棘手問題的解決辦法大多都是 缺了那么幾行代碼。找到解決辦法后,也不要覺得自己菜鳥。 認為這么簡單的問題花費了好長的時間 。 重要的是解決問題的過程。 每解決一個問題,你就進步了一次。