內(nèi)存泄漏經(jīng)常出現(xiàn)在本地代碼中,特別是多線程和發(fā)生異常的情況下,這時(shí)候在delphi環(huán)境下,F(xiàn)astMM4就特別有用。
FastMM4是非常高效可靠的內(nèi)存管理器,用來替代久久不更新的borland內(nèi)存管理器是最好的。地址:http://sourceforge.net/projects/fastmm/
調(diào)試過程如下:
1.打開FastMM4的調(diào)試功能,首先在自己的project里把FastMM4放在最前面,例如:
FastMM4,
Main in ‘Main.pas’ {MainForm},
再修改FastMM4Options.inc,打開全調(diào)試模式。例:
{$define FullDebugMode}
也可以在project中定義編譯常量:FullDebugMode。同時(shí)把FastMM_FullDebugMode.dll拷貝到編譯后生成的可執(zhí)行程序所­在目錄。
再要打開內(nèi)存泄漏報(bào)告:EnableMemoryLeakReporting。一般情況下是缺省打開的。
這樣就打開了全調(diào)試模式,如果發(fā)生內(nèi)存泄漏將會(huì)生成報(bào)告文件,如果在IDE運(yùn)行的時(shí)候還會(huì)彈出一個(gè)對(duì)話框顯示。報(bào)告文件類似:kicoy_MemoryMana­ger_EventLog.txt
2.報(bào)告文件由兩部分組成,并且是每次運(yùn)行append。
第一部分是泄漏的詳細(xì)內(nèi)容,將每個(gè)沒釋放的內(nèi)存塊詳細(xì)信息顯示出來。例:
A memory block has been leaked. The size is: 28
{一個(gè)28字節(jié)的內(nèi)存塊在程序結(jié)束后沒有被釋放}
{這個(gè)內(nèi)存塊在分配的時(shí)候的調(diào)用堆棧,也就是Call
Stack,可以清楚看出調(diào)用函數(shù)的次序。如果是系統(tǒng)dll則還有相應(yīng)的函數(shù)名。}
Stack trace of when this block was allocated (return addresses):
4028E7
4030EC
406649
412365
41236E
411DD3
426B45
427236
42888C
{這個(gè)內(nèi)存類型,如果是字符串string或TObject繼承的對(duì)象則會(huì)顯示名稱。}
The block is currently used for an object of class: Unknown
{將內(nèi)存塊頭256個(gè)字符顯示出現(xiàn),作為內(nèi)容提示。}
Current memory dump of 256 bytes starting at pointer address 107BDD8:
第二部分是總結(jié)性內(nèi)容,例:
{這個(gè)小型內(nèi)存塊泄漏的報(bào)告,如果有大型內(nèi)存塊泄漏則會(huì)加一行專門提示大型內(nèi)存塊泄漏。}
This application has leaked memory. The small block leaks are
(excluding expected leaks registered by pointer):
{21-28字節(jié)的內(nèi)存塊泄漏,未知類型一個(gè)}
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”.
有了這份報(bào)告只不過了解到內(nèi)存泄漏存在,但是哪里沒釋放就還需要更進(jìn)一步地調(diào)查。
調(diào)查的目標(biāo)有:
1.內(nèi)存塊分配在哪個(gè)函數(shù)里哪段代碼。
這個(gè)在報(bào)告里可以結(jié)合內(nèi)容和調(diào)用堆棧來看。前256個(gè)字節(jié)可以進(jìn)行分析,推測(cè)分配者,調(diào)用堆棧就直接指出了分配函數(shù),不過是一些地址,不能直接知道函數(shù)名和代碼­段。這時(shí)候就需要在delphi
ide環(huán)境下查看二進(jìn)制內(nèi)存映像了,就是View CPU功能。
在設(shè)定斷點(diǎn)并停下后,可以View CPU,在菜單View=>Debug
Window=>CPU 快捷鍵:Ctrl+Alt+C
View CPU Window:
正中就是內(nèi)存映像,而且源碼也相應(yīng)地標(biāo)注好了,左邊列的地址就是內(nèi)存報(bào)告中的Call
Stack中的地址,翻頁(yè)找到所對(duì)應(yīng)的代碼就知道哪里分配內(nèi)存了。
2.檢查釋放內(nèi)存的地方是否被調(diào)用,可以用日志或斷點(diǎn)來調(diào)試,如果壓根就沒有釋放內(nèi)存那就補(bǔ)上代碼,如果有卻沒有執(zhí)行則檢查一下執(zhí)行條件是否正確,如果斷點(diǎn)沒起­作用很可能是因?yàn)榇a永遠(yuǎn)不會(huì)被執(zhí)行(死代碼)。
這要靠經(jīng)驗(yàn)和調(diào)試,基本上借助IDE和內(nèi)存報(bào)告就可以很好地防止內(nèi)存泄漏。同時(shí)要加強(qiáng)測(cè)試用例,爭(zhēng)取在測(cè)試用例中能遍歷到所有的代碼和大部分關(guān)鍵功能,這樣內(nèi)存­泄漏報(bào)告就會(huì)更準(zhǔn)確一點(diǎn)。
fastmm每次在程序關(guān)閉后就會(huì)根據(jù)情況生成內(nèi)存泄漏報(bào)告,如果沒有彈出內(nèi)存泄漏警告則恭喜你,內(nèi)存管得很好。
現(xiàn)在總算不用羨慕虛擬機(jī)代碼自動(dòng)回收內(nèi)存了,本地代碼的內(nèi)存管理也不是兩眼一抹黑了,這是可以精確控制的,一切盡在掌握中。
另:
1.內(nèi)存管理不是GC自動(dòng)回收內(nèi)存,而是檢查是否有泄漏。
2.windows系統(tǒng)的內(nèi)存泄漏是無法檢查的,僅限于應(yīng)用程序內(nèi)部,不過檢查出系統(tǒng)泄漏也沒辦法,只能等更新了。
3.檢查泄漏后要自己去檢查代碼補(bǔ)齊內(nèi)存釋放,報(bào)告并不能做這事。
聯(lián)系客服