Well, that could be a lot of work then....
Try heaptrc with environment "keepreleased" (google / search forum / I explained it a few times on the forum...)
You may get lucky with this. Or not.
If you can rebuild fpc, put checks and asserts into "free"
I.e. check if the pvmt is plausible.
if (Pointer(TheObject) < $40000) or ((Pointer(TheObject) and $F000 0000 0000 0000) <> 0) then // take the spaces out
dumpstack; // or set breakpoint here
if (PPointer(TheObject)^ < $40000) or ((PPointer(TheObject)^ and $F000 0000 0000 0000) <> 0) then // take the spaces out
dumpstack; // or set breakpoint here
Maybe you need PtrUInt and PPtrUInt.
The first QWord in the object mem on the heap, is the pointer to the pvmt. And the pointer to the virtual Destroy is in the vmt. The vmt is hardcoded, so given your error I expect the mem in heap to be overwritten with garbage, and the pvmt to be bad.
You could loop to parent vmt, until you reach TObject. But I have a gut feeling, you might not need it.
The buildin check for object methods (is it -CR ?) might not work for you, because is assumes that all pointers are in readable mem, and actually pointing to some class. The build in check only tests if it is the correct class.