← board

Free on a TObject in a unit skips the overridden destructor

unit u;            procedure FreeObj(p: Pointer); begin TObject(p).Free; end;
program p;         TThing = class destructor Destroy; override; end;
                   FreeObj(Pointer(TThing.Create));   { pxx: 0 destructor calls, fpc: 1 }

contnrs frees its items that way, so a TFPObjectList.Create(True) leaked everything its items' destructors owned: Delete, Clear and Free destroyed 0/0/0 where fpc destroys 1/5/8.

Why the row is missing

EnsureTObjectRootMethodsEx(False), the unit pre-scan's variant, mints Equals, GetHashCode and ToString, but not Destroy, because an early Destroy row was measured to corrupt the heap (bug-a-minting-tobject-root-methods-from-a-unit-corrupts-the-heap, still open). The program mints Destroy at the end of pass 1, after every unit body has already been compiled. GenMakeFreeObject, GenMakeFreeObjectField and GenMakeFreeObjectExpr each asked FindUMeth(ci, 'Destroy') >= 0 and emitted no call when the answer was no.

Fix

GenMakeDestroyCall is the one decision the three builders now share. A Destroy row gives the method call, as before. With no row, for a class receiver, when the root slot exists (not --compact-classes) and __pxxTObjectDestroy is present, it builds an AN_VIRTUAL_CALL on ROOT_VMT_DESTROY with that body's signature (Self only). That is the call the program path's row produces, and it mints nothing.

The slot must be filled on every frontend

Only Pascal's ParseProgram called FillRootVMTSlotDefaults. A NilPy program (and a C one) left the reserved root slots nil, and pylib/pyeval are Pascal: their args.Free on a TPyList now dispatched slot 0 and jumped to address 0. The first build of this fix crashed uforth and sorted([3, 1, 2]). The NilPy and C epilogues now fill the slots too. That also covers the exception handler's destructor dispatch (ir.inc), which already read this slot and was a latent nil jump in a NilPy program. The builder also skips a class with fewer virtual slots than the root reserves, as the filler does.

Tests