2012-02-14 23 views
5

對於Web框架,我第一次嘗試匿名方法,並遇到內存管理問題。項目中的匿名方法泄漏內存

這個內存泄漏(Delphi 2009)如何得到修復?

泄漏信息是:

13 - 20個字節:Project27 $ ActRec X 1

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

begin 
    CallMe(procedure begin end); 

    ReportMemoryLeaksOnShutdown := True; 
end. 

相同的泄漏消息 「Project27 $ ActRec×1」 出現不關於開始和結束之間有多少匿名方法,我猜測泄漏是針對TTestProc類型的,而不是個人匿名程序

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

begin 

    ReportMemoryLeaksOnShutdown := True; 

    CallMe(procedure begin end); 

    CallMe(procedure var A: Integer; begin A := 42 ; end); 

end. 
+0

這是在2009年作爲[''QC78066內存泄漏時,在程序單元的開始...結束塊使用匿名方法「](http://qc.embarcadero.com/wc/qcmain的.aspx?d = 78066)。仍然沒有修復。 – 2013-02-28 07:19:26

回答

15

當你在一個過程或函數中聲明一個匿名方法時,它會在該例程超出範圍時被清除。 (這只是過分簡單化,但對於當前的討論來說已經足夠了)。問題是DPR的主程序沒有「超出範圍」。相反,Delphi編譯器會在其末尾插入隱藏的調用System.Halt,該調用永遠不會返回。

所以,如果你這樣寫,你會得到內存泄漏通知。您可以通過將是正常退出,像這樣一個例行的內部匿名方法創建修復:

program Project27; 

type 
    TTestProc = reference to procedure; 

    procedure CallMe(Proc: TTestProc); 
    begin 
    end; 

    procedure Test; 
    begin 
    CallMe(procedure begin end); 
    end; 

begin 
    Test; 
    ReportMemoryLeaksOnShutdown := True; 
end. 
+3

事實上,它比這更多。如果在.dpr文件中聲明一個具有全局作用域的接口變量並將其分配給它,那麼在泄漏檢查運行之前,它將被整理。匿名方法顯然是特殊的。 – 2012-02-14 20:31:15

+1

@David:很奇怪。聽起來像一個bug,然後。有人應該提交一份質量控制報告。 – 2012-02-14 21:27:56

+0

除了調用另一個單元寫入的函數之外,沒有人應該在.dpr中的開始和結束之間做任何事情。即使直接在.dpr中聲明該過程也是一種可怕的做法,並且是不好的風格。 – 2012-02-14 21:52:10

10

我想這是因爲你使用的是.dpr文件中的主要begin..end.塊。當FastMM4檢查內存時,由於它尚未超出範圍,所以在begin..end.範圍內創建的隱藏內存結構不會被釋放。

如果您將匿名方法放在此主要的begin..end.塊之外,則沒有內存泄漏。

我的建議是避免在.dpr文件中放置一些代碼 - 這是大部分時間的錯誤。而IDE不喜歡那樣。爲您自己的代碼使用單獨的單位,並保留.dpr內容。 :)

+0

雖然我同意這是非平凡代碼的最佳選擇,但是在控制檯程序中測試某些算法時,我經常會將所有內容放在dpr中。但即使如此,我的anonmethos和接口等都是本地功能(在dpr中),從不在主要塊中。 – 2016-06-23 15:55:17