此Delphi代码将显示TMyImplementation实例的内存泄漏:

program LeakTest;

uses
  Classes;

type
  MyInterface = interface
  end;

  TMyImplementation = class(TComponent, MyInterface)
  end;

  TMyContainer = class(TObject)
  private
    FInt: MyInterface;
  public
    property Impl: MyInterface read FInt write FInt;
  end;

var
  C: TMyContainer;
begin
  ReportMemoryLeaksOnShutdown := True;

  C := TMyContainer.Create;
  C.Impl := TMyImplementation.Create(nil);
  C.Free;
end.


如果将TComponent替换为TInterfacedObject,并将构造函数更改为Create(),则泄漏将消失。这里的TComponent有什么不同?

非常感谢您的回答。综上所述:说“如果使用接口,它们将被引用计数,因此为您释放了它们”是很容易的,但却是错误的。 -实际上,任何实现接口的类都可以违反此规则。 (并且不会显示任何编译器提示或警告。)

最佳答案

实施上的差异


TComponent._Release不会释放您的实例。
TInterfacedObject._Release释放您的实例。


也许有人可以插话,但我的看法是TComponent并不像我们通常使用接口那样用作引用计数对象。

TComponent._Release的实现

function TComponent._Release: Integer;
begin
  if FVCLComObject = nil then
    Result := -1   // -1 indicates no reference counting is taking place
  else
    Result := IVCLComObject(FVCLComObject)._Release;
end;

07-24 09:30