2016-01-09 7 views
8

Я читаю книгу Ходжеса «Больше кодирования в 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. 

дефект был зафиксирован в X Е8.