1

I have a TObjectList<TUSBDevice>, where TUSBDevice is a class I've made. I tried calling Delete with the index passed as a parameter but that it simply does what TList.Delete() does: removes the pointer from the list but doesn't free the object itself.

The breakpoint I placed on TUSBDevice.Destroy() doesn't break when Delete() is called. I also had a watch on the TObjectList and I can see the item gets removed from the list but the contents at the memory address of the object don't get freed.

Destructor of TUSBDevice:

destructor TUSBDevice.Destroy();
begin
  removeDatabaseEntry();
  filteredFolders.Free();
  fileQueue.Free();
end;
Zhorov
  • 28,486
  • 6
  • 27
  • 52
Radu M.
  • 51
  • 1
  • 4

2 Answers2

2

It's impossible to answer your question since it doesn't contain a minimal reproducible example; the issues doesn't lie in the code you posted, but elsewhere.

Still, the most common cause of an "overridden" destructor not running is that it is in fact not overridden. So I can almost bet that your Destroy declaration is missing the override:

TUSBDevice = class
  // ...
public
  // ...
  destructor Destroy; override;
  // ...
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Would it be a good idea to make my constructor overidden as well? – Radu M. Mar 15 '20 at 12:18
  • 1
    That depends on several factors. A class can have several constructors, and the `TObject` constructor isn't virtual so it *cannot* be overridden. So, if the base class is `TObject`, you have nothing to override. On the other hand, if the base class is `TDevice` and that one has a virtual constructor that must run in order for the object to be properly initialized and your new constructor has the same argument list, then it is a good idea. And of course, don't forget to call the `inherited` constructor (and the inherited destructor, at least if it isn't `TObject.Destroy` which is empty). – Andreas Rejbrand Mar 15 '20 at 12:21
  • 3
    Typically, an overridden constructor *starts with* `inherited;` and an overridden destructor *ends with* `inherited;`. – Andreas Rejbrand Mar 15 '20 at 12:23
  • Yeah, the base class of `TUSBDevice` is `TObject`. Thank you, that makes sense. – Radu M. Mar 15 '20 at 12:23
  • 5
    Always include the call to the inherited constructor and destructor. That way your code doesn't break surprisingly if you ever choose to change the parent class. – David Heffernan Mar 15 '20 at 13:56
  • 1
    I agree with @DavidHeffernan. Always calling the inherited constructor or destructor is best practice. – Andreas Rejbrand Mar 15 '20 at 14:04
-1

Immediately after creating a TObjectList member, you must change his property OwnsObjects to True. This allows the destruction of the objects linked to the Object List when no more is necessary. (i.e., when you delete a member or when you free the TObjectList member)

Pieces := TObjectList<TPiece>.Create;
Pieces.OwnsObjects := True;
  • 1
    _you must change his property OwnsObjects to True_ - no, it is [redundant](https://docwiki.embarcadero.com/CodeExamples/Alexandria/en/Generics_Collections_TObjectList_(Delphi)): _The OwnsObjects property is set by default to true_. – BrakNicku Jan 28 '23 at 12:57