此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;