2016-01-09 18 views
8

Tôi đang đọc sách Hodges "Mã hóa nhiều hơn trong Delphi", phần trên Mẫu nhà máy. Đang cố gắng tìm hiểu nội dung. Làm hỏng mã của tôi thành một đơn vị nhỏ. Tôi sử dụng ReportMemoryLeaksOnShutDown := True; và mã bỏ rơi khiến tôi bị rò rỉ bộ nhớ. Tại sao nó xảy ra và làm thế nào để sửa chữa nó?Mẫu nhà máy, rò rỉ bộ nhớ

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

Cảm ơn câu hỏi mới, câu hỏi này chỉ là những gì chúng tôi thích ở đây –

Trả lời

9

Đây là lỗi trình biên dịch. Việc xác định một phương thức nặc danh trong phần khởi tạo của đơn vị dường như dẫn đến phương thức ẩn danh đó không được hoàn thành, và do đó bị rò rỉ. Trong trường hợp này, tôi sẽ giải quyết vấn đề bằng cách di chuyển mã từ phần khởi tạo đến class constructor.

Vì vậy, loại bỏ các phần initialization hoàn toàn, và thay đổi các nhà xây dựng lớp học để được như thế này:

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

Đây là sinh sản đơn giản nhất mà tôi có thể pha chế:

unit Unit1; 

interface 

implementation 

type 
    TProc = reference to procedure; 

var 
    Foo: TProc; 

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

end. 

Khi bạn đưa này đơn vị trong một dự án, phương pháp ẩn danh được báo cáo là bị rò rỉ.

Nhưng biến thể này không báo cáo bị rò rỉ:

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. 

Khiếm khuyết đã được cố định trong XE8.