【发布时间】:2011-01-17 09:48:17
【问题描述】:
这是一个构造示例。我不想在这里发布原始代码。不过我尝试提取相关部分。
我有一个管理侦听器列表的界面。
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
procedure AddListener (Proc : TListenerProc);
end;
现在我注册一个监听器:
SomeObj.AddListener (MyListener);
procedure MyListener (SomeInt : ISomeInterface);
begin
ExecuteSynchronized (procedure
begin
DoSomething (SomeInt);
end);
end;
我确实遇到了内存泄漏。匿名方法和接口都永远不会被释放。我怀疑这是由于这里的某种循环引用。匿名方法使接口保持活力,接口使匿名方法保持活力。
两个问题:
- 你支持这个解释吗?还是我在这里错过了其他东西?
- 我能做些什么吗?
提前致谢!
编辑:在一个小到可以在此处发布的应用程序中重现此内容并不容易。我现在能做的最好的事情如下。匿名方法在这里没有发布:
program TestMemLeak;
{$APPTYPE CONSOLE}
uses
Generics.Collections, SysUtils;
type
ISomeInterface = interface;
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
['{DB5A336B-3F79-4059-8933-27699203D1B6}']
procedure AddListener (Proc : TListenerProc);
procedure NotifyListeners;
procedure Test;
end;
TSomeInterface = class (TInterfacedObject, ISomeInterface)
strict private
FListeners : TList <TListenerProc>;
protected
procedure AddListener (Proc : TListenerProc);
procedure NotifyListeners;
procedure Test;
public
constructor Create;
destructor Destroy; override;
end;
procedure TSomeInterface.AddListener(Proc: TListenerProc);
begin
FListeners.Add (Proc);
end;
constructor TSomeInterface.Create;
begin
FListeners := TList <TListenerProc>.Create;
end;
destructor TSomeInterface.Destroy;
begin
FreeAndNil (FListeners);
inherited;
end;
procedure TSomeInterface.NotifyListeners;
var
Listener : TListenerProc;
begin
for Listener in FListeners do
Listener (Self);
end;
procedure TSomeInterface.Test;
begin
// do nothing
end;
procedure Execute (Proc : TProc);
begin
Proc;
end;
procedure MyListener (SomeInt : ISomeInterface);
begin
Execute (procedure
begin
SomeInt.Test;
end);
end;
var
Obj : ISomeInterface;
begin
try
ReportMemoryLeaksOnShutdown := True;
Obj := TSomeInterface.Create;
Obj.AddListener (MyListener);
Obj.NotifyListeners;
Obj := nil;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
【问题讨论】:
-
您应该向我们展示 AddListener 的工作原理。
-
我只是把它们放在
TList <TListenerProc>. -
我看到的所有代码看起来都不错。问题一定出在隐藏的部分。你能展示一个产生泄漏的完整例子吗?
-
查看我对 Mghie 回答的评论。检查看看是否有帮助。
标签: delphi memory-management interface delphi-2010 anonymous-methods