Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An object in a TObjectList is not freed when a TObjectList.Clear is called

Tags:

delphi

See the code below. I was removed a lot of code for the sake of simplicity, however the remaining code is still quite long, sorry :(

  IObserver = interface
    ['{1DD212F8-BD5E-47BF-9A3B-39EF7B9D99B5}']
    procedure Update(Observable: IObservable);
  end;

  TObserver = class abstract (TSingletonImplementation, IObserver)
    strict protected
      //...
    public
      constructor Create;
      destructor Destroy; virtual;
      //IObserver
      procedure Update(Observable: IObservable); virtual; abstract;
      //... 
  end;

  TShapeModification = class abstract (TObserver)
    strict protected
      //...
    public
      //Doesn't have a constructor
  end;

  TRangePointModification = class(TShapeModification)
    strict private
      //...
    public
      constructor Create(...);
      //...
  end;

  constructor TRangePointModification.Create(...);
  begin
    inherited Create;
    //...
  end;

Then at some point:

TClientClass = class
  strict private
    fList: TObjectList<TShapeModification>;
  public
    constructor Create();
    destructor Destroy(); override;
    procedure Add(ShapeModification: TShapeModification);
end;

constructor TClientClass.Create;
begin
  Self.fList:=TObjectList<TShapeModification>.Create(true);
end;

destructor TClientClass.Destroy;
begin
  Self.fList.Clear;
  FreeAndNil(Self.fList);
end;

Finally, at some point:

var
  MyClient: TClientClass;
begin
  MyClient:=TClientClass.Create();
  MyClient.Add(TRangePointModification.Create());
  MyClient.Free;
end;

When the MyClient is freed, the TClientClass destructor is called then the internal fList is supposed to be cleared but the destructor of TRangePointModification (from TObserver) is not called. WHY not?

(I am using Delphi 10.2 Tokyo)

like image 207
Delmo Avatar asked Jul 23 '18 09:07

Delmo


1 Answers

Look into the warnings - compiler tells you what is wrong:

W1010 Method 'Destroy' hides virtual method of base type ...

Always put override on your destructors (not virtual!)- otherwise the call to Free will not execute the code you put into them.

So as a basic advice:

  1. always write code that produces zero warnings or hints - they most likely point to a defect that you will encounter sooner or later

  2. put a breakpoint into code you suspect to be defect - even when ignoring the compiler warning you would have seen the call to Clear was never even made

like image 102
Stefan Glienke Avatar answered Oct 08 '22 21:10

Stefan Glienke