[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