天天看點

檢查記憶體洩漏

檢查記憶體洩漏

linux+gcc用valgrind,windows+msvc用vs調試功能。

如果是在windows上跑mingw就坑爹了,要麼買專門的商業檢測軟體,要麼用代碼侵入的方式,重載operator new,接入記憶體洩漏檢測代碼

隻要每一個cpp在展開後都能看見這幾行(​​https://github.com/vczh-libraries/Vlpp/blob/master/Source/Basic.h​​):

在程式退出的時候,調用_CrtDumpMemoryLeaks函數,Visual Studio的output視窗就會列印所有沒有釋放的東西(包括全局變量——是以不要在全局變量裡面使用非指針或數字類型),輕按兩下可以跳進代碼。

我都配置成debug模式會檢查,每次運作的時候都在檢查,有時候我都忘記他在檢查了然後突然就蹦出來了消息說我記憶體洩漏了,然後馬上改。是以我的程式絕對沒有記憶體洩漏(逃

如果是Windows的話可以利用在DEBUG環境下檢查

除非自己實作一個GC。記憶體洩漏的本質是配置設定了記憶體,沒有釋放,而且将來也不會再使用了。上面回答說重載new, malloc都是治标不治本的方法,即使你記錄了所有已配置設定的未釋放的記憶體塊,如果你沒有辦法判斷将來這塊記憶體是否會再被使用的話,你敢随便釋放嗎?如果你能判斷出将來一定不會使用了,那麼等于你實作了一個GC。要解決這個問題隻能從代碼編寫的規範來考慮,記憶體的配置設定和釋放控制在同一個scope裡面,盡量避免在一個函數裡面配置設定記憶體,再在另一個函數裡面去釋放。如果确實需要配置設定一塊記憶體作為運作時全局使用,可以考慮設定initialize和destroy方法分别在work flow開始和結束的時候調用。

gcc的asan

好像4.8以上的gcc自帶asan.

加編譯選項和連結asan庫就行,程序退出的時候,幫你列印出來所有申請未釋放的記憶體

因為是一個新特性,它被安排在dev分支(Qt 5.2)。但是您可以把它cherry-pick到Qt 5.0。然後您在配置Qt時使用-address-sanitizer,為您的程式執行qmake CONFIG+=address_sanitizer。

如果您不想cherry-pick,您也可以手動為qmake設定指令行參數MAKE_CXXFLAGS、QMAKE_CFLAGS和QMAKE_LFLAGS:

要啟用例如位址清理器,您必須編寫:

消毒劑選項在Qt的mkspecs(​<code>​mkspecs/features/sanitizer.prf​</code>​和​<code>​mkspecs/common/sanitize.conf​</code>​)中定義,當您添加時會加載它​<code>​CONFIG += sanitizer​</code>​。快速浏覽我的​<code>​sanitizer.prf​</code>​(Qt 5.7.0),可以看到特定的消毒劑是:

​<code>​sanitize_address​</code>​

​<code>​sanitize_memory​</code>​

​<code>​sanitize_thread​</code>​

​<code>​sanitize_undefined​</code>​

如果是Windows,考慮下Visual Leak Detector,這個對洩露點資訊定位相當不錯;如果是Linux,考慮下Valgrind,檢測記憶體使用以及線程方面的Bug功能非常強大。

使用工具隻能查出因為自己代碼造成的記憶體洩漏,對于因為錯誤調用系統API造成的記憶體洩漏還是隻能通過查log和review代碼來定位,沒辦法。

============= End