delphi – 接口,匿名方法和内存泄漏

前端之家收集整理的这篇文章主要介绍了delphi – 接口,匿名方法和内存泄漏前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一个构建的例子。我不想在这里发布原始代码。我试图提取相关的部分。

我有一个接口来管理一个监听器列表。

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;

我确实有内存泄漏。匿名方法和接口都不会被释放。我怀疑这是因为这里的某种循环引用。匿名方法保持接口alife和接口保持匿名方法alife。

两个问题:

支持这个解释吗?还是我在这里遗漏了别的东西?
有什么可以做的吗?

提前致谢!

编辑:在一个足够小的应用程序中再现这个并不容易,可以在这里发布。现在我能做的最好的就是如下。匿名方法不会在这里发布:

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这里)。这不能在周围工作或设计。看起来像编译器中的一个错误

编辑:

或者也许这是内存泄漏检测的问题。它与参数是一个接口无关,无参数的过程导致相同的“泄漏”。很奇怪。

猜你在找的Delphi相关文章