[fpc-pascal] Delegate Interface class does not seem to be referenced counted
Graeme Geldenhuys
mailinglists at geldenhuys.co.uk
Thu Aug 18 11:53:58 CEST 2016
On 2016-08-10 16:47, Tony Whyman wrote:
> You are explicitly freeing MyClass. My point is that with reference
> counted interfaces and in the example I posted, you shouldn't have to
> explicitly free the delegated interface. It should be freed
> automatically as soon as it goes out of scope.
Let me explain with a slightly modified example. NOTE: I get the exact
same behaviour under FPC 2.6.4 and under Delphi 7.
The reason I [must] free the TMyClass instance is because it is a
TObject descendant. Obviously I can query the interface from that
instance and don't have to free anything interface related.
In the second test project I create a TMyInterface instance, which is a
TInterfaceObject descendant. I store it directly to a interface
reference variable, and then use the interface as needed. I don't need
to free anything here, because TInterfaceObject is reference counted and
will free itself once it goes out of scope.
I think you are getting confused between TObject and TInterfaceObject
instances, and what is required from both.
=====================[ test2.pas ]===========================
program test2;
{$mode objfpc}{$H+}
{$interfaces com}
{ Delegating to an interface-type property }
uses
Classes,
SysUtils;
type
IMyInterface = interface
['{9CF79E28-6527-11E6-9A7E-C86000E37EB0}']
procedure P1;
procedure P2;
end;
TMyInterface = class(TInterfacedObject, IMyInterface)
private
procedure P1;
procedure P2;
public
constructor Create;
destructor Destroy; override;
end;
TMyClass = class(TObject, IMyInterface)
FMyInterface: IMyInterface;
property MyInterface: IMyInterface read FMyInterface implements
IMyInterface;
public
constructor Create;
destructor Destroy; override;
end;
procedure TMyInterface.P1;
begin
writeln('TMyInterface.P1');
end;
procedure TMyInterface.P2;
begin
writeln('TMyInterface.P2');
end;
constructor TMyInterface.Create;
begin
writeln('Creating ',ClassName);
end;
destructor TMyInterface.Destroy;
begin
writeln('Destroying ',ClassName);
inherited Destroy;
end;
{ TMyClass }
constructor TMyClass.Create;
begin
writeln('Creating ',ClassName);
FMyInterface := TMyInterface.Create;
end;
destructor TMyClass.Destroy;
begin
writeln('Destroying ',ClassName);
inherited Destroy;
end;
procedure Test1;
var
MyClass: TMyClass;
MyInterface: IMyInterface;
begin
MyInterface := nil;
MyClass := TMyClass.Create;
if Supports(MyClass, IMyInterface, MyInterface) then
begin
MyInterface.P1;
MyInterface.P2;
end;
MyClass.Free; // because TMyClass is a TObject descendant
end;
procedure Test2;
var
MyInterface: IMyInterface;
begin
MyInterface := TMyInterface.Create;
MyInterface.P1;
MyInterface.P2;
MyInterface := nil; // optional
end;
begin
Test1;
writeln('=========================');
Test2;
end.
===================[ end ]===================================
And the output of the program gives this....
$ ./test2.exe
Creating TMyClass
Creating TMyInterface
TMyInterface.P1
TMyInterface.P2
Destroying TMyClass
Destroying TMyInterface
=========================
Creating TMyInterface
TMyInterface.P1
TMyInterface.P2
Destroying TMyInterface
which is expected and correct.
Regards,
Graeme
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/
My public PGP key: http://tinyurl.com/graeme-pgp
More information about the fpc-pascal
mailing list