2016-01-09 37 views
8

我在閱讀Hodges的書籍「Delphi中的更多編碼」,工廠模式部分。 試圖學習的東西。將我的代碼分解成小單元。 我使用ReportMemoryLeaksOnShutDown := True;和休耕代碼導致我內存泄漏。爲什麼會發生,我該如何解決?工廠模式,內存泄漏

unit Unit2; 

interface 

uses 
    Generics.Collections, System.SysUtils; 

type 
    TGatewayTpe = (gtSwedbank, gtDNB); 

type 
    TBaseGateway = class 

    end; 

type 
    TSwedbankGateway = class(TBaseGateway) 
    end; 

type 
    TGatewayFunction = reference to function: TBaseGateway; 

type 
    TGatewayTypeAndFunction = record 
    GatewayType: TGatewayTpe; 
    GatewayFunction: TGatewayFunction; 
    end; 

type 
    TGatewayFactory = class 
    strict private 
    class var FGatewayTypeAndFunctionList: TList<TGatewayTypeAndFunction>; 
    public 
    class constructor Create; 
    class destructor Destroy; 
    class procedure AddGateway(const AGatewayType: TGatewayTpe; 
     const AGatewayFunction: TGatewayFunction); 
    end; 

implementation 

class procedure TGatewayFactory.AddGateway(const AGatewayType: TGatewayTpe; 
    const AGatewayFunction: TGatewayFunction); 

var 
    _GatewayTypeAndFunction: TGatewayTypeAndFunction; 
begin 
    _GatewayTypeAndFunction.GatewayType := AGatewayType; 
    _GatewayTypeAndFunction.GatewayFunction := AGatewayFunction; 

    FGatewayTypeAndFunctionList.Add(_GatewayTypeAndFunction); 
end; 

class constructor TGatewayFactory.Create; 
begin 
    FGatewayTypeAndFunctionList := TList<TGatewayTypeAndFunction>.Create; 
end; 

class destructor TGatewayFactory.Destroy; 
begin 
    FreeAndNil(FGatewayTypeAndFunctionList); 
end; 

initialization 
    TGatewayFactory.AddGateway(
    gtSwedbank, 
    function: TBaseGateway 
    begin 
     Result := TSwedbankGateway.Create; 
    end 
); 

end. 
+1

感謝您提出的新問題,這個就是我們喜歡的 –

回答

9

這是一個編譯器缺陷。在單元的初始化部分中定義匿名方法似乎會導致匿名方法沒有完成,因此泄漏。在這種情況下,我會通過將代碼從初始化部分移動到class constructor來解決此問題。

所以,徹底去除initialization部分,並更改類的構造函數是這樣的:

class constructor TGatewayFactory.Create; 
begin 
    FGatewayTypeAndFunctionList := TList<TGatewayTypeAndFunction>.Create; 
    AddGateway(
    gtSwedbank, 
     function: TBaseGateway 
     begin 
     Result := TSwedbankGateway.Create; 
     end 
); 
end; 

這裏是我可以編造的最簡單的再現:

unit Unit1; 

interface 

implementation 

type 
    TProc = reference to procedure; 

var 
    Foo: TProc; 

initialization 
    ReportMemoryLeaksOnShutdown := True; 
    Foo := procedure begin end; 

end. 

如果包括此單位在一個項目中,匿名方法被報告爲泄漏。

但這種變異並不報告泄漏:

unit Unit1; 

interface 

implementation 

type 
    TProc = reference to procedure; 

var 
    Foo: TProc; 

procedure DoInit; 
begin 
    Foo := procedure begin end; 
end; 

initialization 
    ReportMemoryLeaksOnShutdown := True; 
    DoInit; 

end. 

缺陷固定在XE8。