Rosanna Trevisan
Rosanna Trevisan

Reputation: 452

Delphi reference counting for subclasses

Say that I have a situation like this:

ITest = interface
 procedure somethingHere();
end;

TImpl = class(TInterfacedObject, ITest)
 procedure somethingHere();
end;

TImplSub = class(TImpl)

end;

Given the code above I am able to use this kind of code without any memory leak if I don't use the try-finally statement:

var a: ITest;
begin
 a := TImpl.Create;
end;

Is this the same for the subclass?

var a: ITest;
begin
 a := TImplSub.Create;
end;

I think that since TImplSub is a subclass of TImpl, TImplSub inherits TInterfacedObject and ITest from the father. Does the above code leak?

This may be not related but how can I check if the code above leaks or not?

Upvotes: 11

Views: 195

Answers (2)

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28512

Reference counting for interface references is triggered with _AddRef and _Release methods that are in this case implemented in TInterfacedObject. Your subclass inherits that reference counting behavior.

You can use, actually you must use, interface references to store your subclassed object instance, the way you coded it. (Not using interface reference for storing reference counted object instances breaks reference counting mechanism)

Following code does not leak, and does not require try...finally block because destruction is automatic.

var a: ITest;
begin
 a := TImplSub.Create;
end;

To check for memory leaks under Windows compiler you can use ReportMemoryLeaksOnShutdown

begin
  ReportMemoryLeaksOnShutdown := true;
  ...
end.

Another way of testing whether object is destroyed while you are investigating specific behavior is to override destructor and set breakpoint there.

Upvotes: 13

Rosanna Trevisan
Rosanna Trevisan

Reputation: 452

Thanks to the comments (@nil user) I have managed to make a test like this

type
 ITest = interface
   procedure test;
 end;

 TProva = class(TInterfacedObject, ITest)
   procedure test;
 end;

 TProvaSub = class(TProva)
   procedure testDue;
 end;

And then if you try to run this code (in debug mode with F9):

procedure TForm1.Button1Click(Sender: TObject);
var a: ITest;
begin    
 a := TProvaSub.Create;
 a.test;    
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown:=DebugHook<>0;
end;

WHen I close the form I DON'T have a leak report.


My conclusion: TProvaSub has a piece of TProva inside itself (since it's a subclass) and so it inherits the _AddRef and _Release. So the code is good and doesn't leak!

Upvotes: 5

Related Questions