2016-01-09 29 views
8

Czytam książkę Hodgesa "Więcej kodowania w Delphi", sekcja o fabrycznym wzorze. Próbujesz się czegoś nauczyć. Zepsułem mój kod na małą jednostkę. Używam ReportMemoryLeaksOnShutDown := True; i odłogiem kodu produkuje mi wyciek pamięci. Dlaczego tak się dzieje i jak mogę to naprawić?Fabryczny wzór, wyciek pamięci

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

Dzięki za nowe pytanie, to jest to, co lubimy tutaj –

Odpowiedz

9

To jest usterka kompilatora. Zdefiniowanie anonimowej metody w sekcji inicjalizacyjnej jednostki wydaje się prowadzić do tego, że anonimowa metoda nie została sfinalizowana, a zatem wyciekła. W takim przypadku obejdę ten problem, przenosząc kod z sekcji inicjalizacji do class constructor.

Więc usunąć sekcję initialization całkowicie i zmień konstruktora klasy być tak:

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

Oto najprostszy układ rozrodczy, że mogę wymyślać:

unit Unit1; 

interface 

implementation 

type 
    TProc = reference to procedure; 

var 
    Foo: TProc; 

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

end. 

Po dołączeniu tego jednostka w projekcie, metoda anonimowa jest zgłaszana jako wyciek.

Ale ten wariant nie zgłasza przeciek:

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. 

Defekt został ustalony w XE8.