天天看點

FastMM 定位記憶體洩露的代碼位置

FastMM 定位記憶體洩露的代碼位置

開源的FastMM,使用很簡單,在工程的第一行引用FastMM4即可(注意,一定要在第一個Uses的位置),可以在調試程式時提示記憶體洩露情況,還可以生成報告。

在Delphi2007以後版本中,使用更加簡單,隻需要在工程開始的位置加上語句:

ReportMemoryLeaksOnShutdown := True;就可以了,并且在運作時不會出現提示。如果想要生成檔案報告,還需要FastMM4,Delphi中沒有别的設定可以生成檔案報告。

可以修改FastMM4Options.inc中的參數開關來修改記憶體管理的相關設定。

使用說明如下:

1.打開FastMM4的調試功能

首先在自己的project裡把FastMM4放在最前面,例如:  

FastMM4,  

Main   in   ‘Main.pas’   {MainForm},  

再修改FastMM4Options.inc,打開全調試模式。例:  

{$define   FullDebugMode}  

也可以在project中定義編譯常量:FullDebugMode。

同時把FastMM_FullDebugMode.dll拷貝到編譯後生成的可執行程式所在目錄。

再要打開記憶體洩漏報告:EnableMemoryLeakReporting。一般情況下是預設打開的。  這樣就打開了全調試模式,如果發生記憶體洩漏将會生成報告檔案,如果在IDE運作的時候還會彈出一個對話框顯示。報告檔案類似:XXX_MemoryManager_EventLog.txt  

2.報告檔案由兩部分組成,并且是每次運作append。  

第一部分是洩漏的詳細内容,将每個沒釋放的記憶體塊詳細資訊顯示出來。例:  

A   memory   block   has   been   leaked.   The   size   is:   28      

{一個28位元組的記憶體塊在程式結束後沒有被釋放}

{這個記憶體塊在配置設定的時候的調用堆棧,也就是Call   Stack,可以清楚看出調用函數的次序。如果是系統dll則還有相應的函數名。}

Stack   trace   of   when   this   block   was   allocated   (return   addresses):  

4028E7

4030EC

406649

412365

41236E

411DD3

426B45

427236

42888C

{這個記憶體類型,如果是字元串string或TObject繼承的對象則會顯示名稱及行号。}

The   block   is   currently   used   for   an   object   of   class:   Unknown  

{将記憶體塊頭256個字元顯示出現,作為内容提示。}

Current   memory   dump   of   256   bytes   starting   at   pointer   address   107BDD8:

第二部分是總結性内容,例:

{這個小型記憶體塊洩漏的報告,如果有大型記憶體塊洩漏則會加一行專門提示大型記憶體塊洩漏。}This   application   has   leaked   memory.   The   small   block   leaks   are   (excluding   expected   leaks   registered   by   pointer):  

{21-28位元組的記憶體塊洩漏,未知類型一個}

21   -   28   bytes:   Unknown   x   1

Note:   Memory   leak   detail   is   logged   to   a   text   file   in   the   same   folder   as   this   application.   To   disable   this   memory   leak   check,   undefine   “EnableMemoryLeakReporting”.  

有了這份報告隻不過了解到記憶體洩漏存在,但是哪裡沒釋放就還需要更進一步地調查。

調查的目标有:

1.    記憶體塊配置設定在哪個函數裡哪段代碼。

這個在報告裡可以結合内容和調用堆棧來看。前256個位元組可以進行分析,推測配置設定者,調用堆棧就直接指出了配置設定函數,不過是一些位址,不能直接知道函數名和代碼段。這時候就需要在delphi   ide環境下檢視二進制記憶體映像了,就是View   CPU功能。在設定斷點并停下後,可以View   CPU,在菜單View=>Debug   Window=>CPU ,快捷鍵:Ctrl+Alt+C,View CPU視窗正中就是記憶體映像,而且源碼也相應地标注好了,左邊列的位址就是記憶體報告中的Call   Stack中的位址,翻頁找到所對應的代碼就知道哪裡配置設定記憶體了。

2.檢查釋放記憶體的地方是否被調用

可以用日志或斷點來調試,如果壓根就沒有釋放記憶體那就補上代碼,如果有卻沒有執行則檢查一下執行條件是否正确,如果斷點沒起作用很可能是因為代碼永遠不會被執行(死代碼)。這要靠經驗和調試,基本上借助IDE和記憶體報告就可以很好地防止記憶體洩漏。同時要加強測試用例,争取在測試用例中能周遊到所有的代碼和大部分關鍵功能,這樣記憶體洩漏報告就會更準确一點。

fastmm每次在程式關閉後就會根據情況生成記憶體洩漏報告,如果沒有彈出記憶體洩漏警告則恭喜你,記憶體管得很好。

另外:  

  1).記憶體管理不是GC自動回收記憶體,而是檢查是否有洩漏。  

  2).windows系統的記憶體洩漏是無法檢查的,僅限于應用程式内部,不過檢查出系統洩漏也沒辦法,隻能等更新了。      

  3).檢查洩漏後要自己去檢查代碼補齊記憶體釋放,報告并不能做這事