gpt4 book ai didi

delphi - 接口(interface)、匿名方法和内存泄漏

转载 作者:行者123 更新时间:2023-12-03 14:35:41 26 4
gpt4 key购买 nike

这是一个构建的示例。我不想在这里发布原始代码。我尝试提取相关部分。

我有一个管理监听器列表的界面。

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;

我确实遇到了内存泄漏。匿名方法和接口(interface)都永远不会被释放。我怀疑这是由于此处的某种循环引用造成的。匿名方法使接口(interface)保持活力,接口(interface)使匿名方法保持活力。

两个问题:

  1. 你支持这个解释吗?或者我在这里还缺少其他东西吗?
  2. 我能做些什么吗?

提前致谢!

<小时/>

编辑:在一个小到足以将其发布到此处的应用程序中重现此内容并不容易。我现在能做的最好的事情如下。匿名方法不会在这里被释放:

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.

最佳答案

您的代码远非最少。以下内容:

program AnonymousMemLeak;

{$APPTYPE CONSOLE}

uses
SysUtils;

type
TListenerProc = reference to procedure (SomeInt : IInterface);

procedure MyListener (SomeInt : IInterface);
begin
end;

var
Listener: TListenerProc;

begin
try
ReportMemoryLeaksOnShutdown := True;

Listener := MyListener;
Listener := nil;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

有同样的问题(此处为 Delphi 2009)。这是无法解决或设计的。在我看来就像编译器中的错误。

编辑:

或者这可能是内存泄漏检测的问题。它与参数是接口(interface)无关,无参数过程会导致相同的“泄漏”。很奇怪。

关于delphi - 接口(interface)、匿名方法和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2273194/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com