[fpc-devel] Interfaced Object leak in inherited Object
Michael Van Canneyt
michael at freepascal.org
Mon Jun 13 11:40:05 CEST 2005
On Mon, 13 Jun 2005, alphax wrote:
> 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.
This is normal behviour (although maybe not desirable behaviour).
You *must* call the destructor of your object, that is why it is there:
to clean up.
Michael.
>
> 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