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?
The reason for that is that Delphi's automatic reference counting only works with interfaces. With variables declared as interfaces, automatic reference counting will be handled by the compiler, and you will not have to put in any deallocation calls in order to prevent memory leaks.
When the reference count goes to zero, the object is disposed of. Failure to do the reference counting correctly results in bugs that are sometimes very hard to diagnose. Symptoms of such bugs may be objects "disappearing" for unknown reason, or memory leaks.
QuickOPC is not special in respect to COM reference counting, and the rules that apply to QuickOPC usage in Delphi are the general rules that apply to any COM component. We have, however, put together a short set of recommendations that should help you to write bug-free code more easily, in this respect.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With