工厂模式,内存泄漏
Factory pattern, memory leak
我正在阅读 Hodges 的书 "More Coding in 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.
这是一个编译器缺陷。在单元的初始化部分定义匿名方法似乎会导致该匿名方法未被最终确定,从而导致泄漏。在这种情况下,我会通过将代码从初始化部分移动到 class constructor
.
来解决这个问题
所以,完全删除 initialization
部分,并将 class 构造函数更改为如下所示:
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 中修复。
我正在阅读 Hodges 的书 "More Coding in 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.
这是一个编译器缺陷。在单元的初始化部分定义匿名方法似乎会导致该匿名方法未被最终确定,从而导致泄漏。在这种情况下,我会通过将代码从初始化部分移动到 class constructor
.
所以,完全删除 initialization
部分,并将 class 构造函数更改为如下所示:
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 中修复。