Why do interface implementations based on TComponent leak memory?

delphi, delphi-2009, interface, memory-leaks

Solution

Differences in implementation

- `TComponent._Release` does not free your instance.

- `TInterfacedObject._Release` does free your instance.

Perhaps someone can chime in but my take on this is that `TComponent` is not meant to be used as a reference counted object the way we normally use interfaces.

Implementation of 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;

Problem

This Delphi code will show a memory leak for an instance of 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. ``` If TComponent is replaced by TInterfacedObject and the constructor changed to Create(), the leak disappears. What is different with TComponent here? Many thanks for the answers. To sum up: it is easy, but wrong, to say "If you are using interfaces, they are reference counted and hence they are freed for you." - Actually any class which implements an interface can break this rule. (And there will be no compiler hint or warning be shown.)

Original source