[fpc-devel] Interfaced Object leak in inherited Object
    alphax 
    acmui_2004 at 163.com
       
    Mon Jun 13 09:31:53 CEST 2005
    
    
  
It seems a bug in FPC 2.0.0.(Delphi 7.1 also has this bug)
Assumes there is an object(not class) declaration, the object has a IInterface field. If we declare another object derive from it, in the cleanup procedure of that decendant leak to clear the IInterface references.
The test program is follow:
//===================================================================
program test_obj_inherit;
{
  bug: Interfaced Object leak in inherited Object
  environment: win2k fpc2.0.0
  date: 2005.06.13
}
{$mode objfpc}
uses
  SysUtils, Variants;
type
  TInterfacedObj = class(TInterfacedObject)
    destructor Destroy; override;
  end;
  TObj1 = object
    I: IInterface;
    constructor Create;
    procedure Which; virtual;
  end;
  PObj1 = ^TObj1;
  TObj2 = object(TObj1)
    constructor Create;
    procedure Which; virtual;
  end;
  PObj2 = ^TObj2;
  TObj3 = object(TObj1)
    //object keep a Variant
    V: Variant;
    constructor Create;
    procedure Which; virtual;
  end;
  PObj3 = ^TObj3;
var
  //used to check the interfaced object is whether or not released
  InterfacedObjReleased: Boolean;
destructor TInterfacedObj.Destroy;
  begin
    InterfacedObjReleased := True;
  end;
constructor TObj1.Create;
  begin
  end;
procedure TObj1.Which;
  begin
    WriteLn('  This is TObj1');
  end;
constructor TObj2.Create;
  begin
  end;
procedure TObj2.Which;
  begin
    WriteLn('  This is TObj2');
  end;
constructor TObj3.Create;
  begin
  end;
procedure TObj3.Which;
  begin
    WriteLn('  This is TObj3');
  end;
{==Test TObj1==}
procedure Test1_1;
  var
    Obj: PObj1;
  begin
    WriteLn('Use Object Pointer');
    New(Obj, Create);
    Obj^.I := TInterfacedObj.Create();
    Obj^.Which();
    Dispose(Obj);
  end;
procedure Test1_2;
  var
    Obj: TObj1;
  begin
    WriteLn('Use Object directly');
    Obj.Create();
    Obj.I := TInterfacedObj.Create();
    Obj.Which();
  end;
{==Test TObj2==}
procedure Test2_1;
  var
    Obj: PObj2;
  begin
    WriteLn('Use Object Pointer');
    Obj := New(PObj2, Create);
    Obj^.I := TInterfacedObj.Create();
    Obj^.Which();
    Dispose(Obj); //here, the I should be release
  end;
procedure Test2_2;
  var
    Obj: TObj2;
  begin
    WriteLn('Use Object directly');
    Obj.Create();
    Obj.I := TInterfacedObj.Create();
    Obj.Which();
  end; //afetr Test2_2 return the I should be release
{==Test TObj3==}
operator := (const I: IInterface): Variant;
  begin
    VarClear(Result);
    with TVarData(Result) do
    begin
      vtype := varunknown;
      IInterface(vunknown) := I;
    end;
  end;
procedure Test3_1;
  var
    Obj: PObj3;
  begin
    WriteLn('Use Object Pointer');
    Obj := New(PObj3, Create);
    Obj^.V := TInterfacedObj.Create();
    Obj^.Which();
    Dispose(Obj); //here, the V should be cleanup
  end;
procedure Test3_2;
  var
    Obj: TObj3;
  begin
    WriteLn('Use Object directly');
    Obj.Create();
    Obj.V := TInterfacedObj.Create();
    Obj.Which();
  end; //afetr Test3_2 return the V should be cleanup
procedure CheckReleased;
  begin
    if InterfacedObjReleased then
      WriteLn('  InterfacedObject Release, OK')
    else
      WriteLn('  InterfacedObject is *NOT* Released, Failure');
    WriteLn;
    InterfacedObjReleased := False;
  end;
begin
  WriteLn;
  Test1_1();
  CheckReleased();
  Test1_2();
  CheckReleased();
  Test2_1();  //<- The InterfacedObject leak in this call
  CheckReleased();
  Test2_2();  //<- The InterfacedObject leak in this call
  CheckReleased();
  Test3_1();
  CheckReleased();
  Test3_2();
  CheckReleased();
  WriteLn;
end.
//===================================================================
    
    
More information about the fpc-devel
mailing list