Delphi的内存管理及内存泄露问题
這幾天因為一個程序長時間運行出現比較嚴重的內存泄露問題,開始關注了一下內存管理方面的東西,以前也注意內存管理,創建了對象及時釋放,但總有忘了處理的情況。
在Delphi中沒有自動回收機制,所以一定要及時釋放使用的內存,雖然有時小的內存泄露并不會造成太大的問題。
Delphi中檢測內存泄露可以使用開源的FastMM(http://sourceforge.net/projects/fastmm/),使用很簡單,在工程的第一行引用FastMM4即可(注意,一定要在第一個Uses的位置),可以在調試程序時提示內存泄露情況,還可以生成報告。
在Delphi2010中,使用更加簡單,只需要在工程開始的位置加上語句:
ReportMemoryLeaksOnShutdown := DebugHook<>0;
就可以了,并且在運行時不會出現提示。如果想要生成文件報告,還需要FastMM4,Delphi2010中或許有別的設置可以生成文件報告,沒有找到。
可以修改FastMM4Options.inc中的參數開關來修改內存管理的相關設置。
后來在網上又發現了一個說是讓Delphi支持自動垃圾回收的東東,很高興,看了一下:
http://www.hpl.hp.com/personal/Hans_Boehm/gc/
有編譯好的,可以支持多種開發語言,也可以支持Delphi,于是測試了一下,發現這個程序好像只是在系統退出時進行垃圾回收,比如你有兩個窗體,form1和form2,form1調用form2,而form2中創建了一個對象沒有釋放,則在你注銷form2的時候form2中使用的對象的內存并沒有釋放,而是要等到程序結束,所以這種垃圾回收時機有點晚了,如果你程序有大的內存泄露會導至系統內存問題的話,這個程序并不會幫你解決這個問題。(沒有詳細測試,哪位大俠有經驗可以指點指點? :-)?? )
所以,最好的辦法還是你自己在寫程序的時候一定要注意釋放掉使用的內存,可以借助fastmm來幫你找可能的內存泄露。
?
附:FastMM的使用(轉自網絡)
?使用說明如下: ? ?
? 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 ? Window: ? ? ?
? ?
? 正中就是內存映像,而且源碼也相應地標注好了,左邊列的地址就是內存報告中的Call ? Stack中的地址,翻頁找到所對應的代碼就知道哪里分配內存了。 ?
? ?
? 2.檢查釋放內存的地方是否被調用,可以用日志或斷點來調試,如果壓根就沒有釋放內存那就補上代碼,如果有卻沒有執行則檢查一下執行條件是否正確,如果斷點沒起作用很可能是因為代碼永遠不會被執行(死代碼)。 ?
? ?
? 這要靠經驗和調試,基本上借助IDE和內存報告就可以很好地防止內存泄漏。同時要加強測試用例,爭取在測試用例中能遍歷到所有的代碼和大部分關鍵功能,這樣內存泄漏報告就會更準確一點。 ?
? ?
? fastmm每次在程序關閉后就會根據情況生成內存泄漏報告,如果沒有彈出內存泄漏警告則恭喜你,內存管得很好。 ?
? ?
? 另: ?
? ?
? 1.內存管理不是GC自動回收內存,而是檢查是否有泄漏。 ?
? ?
? 2.windows系統的內存泄漏是無法檢查的,僅限于應用程序內部,不過檢查出系統泄漏也沒辦法,只能等更新了。 ?
? ?
? 3.檢查泄漏后要自己去檢查代碼補齊內存釋放,報告并不能做這事。
?
I'd like morning better if they started later !
----garfield
?
轉載于:https://www.cnblogs.com/GarfieldTom/archive/2009/12/09/1619876.html
總結
以上是生活随笔為你收集整理的Delphi的内存管理及内存泄露问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用cheat engine以及VC编写
- 下一篇: 自己封装线程(Demo)