Old-style Delphi objects have been broken since the release of Delphi 2, perhaps earlier. They do not do inheritance well when they have fields of compiler-managed types, such as string
or dynamic arrays. There was a discussion about it in 2004 on comp.lang.pascal.delphi.misc. Here was the code to reproduce it:
type
TBase = object
public
s: string;
end;
TDerived = object(TBase)
end;
procedure test;
var
obj: TDerived; //okay for TBase!
begin
assert(obj.s = , uninitialized dynamic variable );
end;
And in fact it s only OK for TBase
by accident because of how the function s prologue code happens to be generated. Putting additional code in that function can make it crash anyway.
Indeed, it s exactly as you ve observed — old-style objects don t get initialized properly. Their string fields don t start out holding an empty string; instead, they hold garbage, and so it s not even possible to initialize them yourself without using something like FillChar
.
This appears to be due to the variables being local variables. Unit-scope ("global") variables seem to work OK. Variables that are declared at unit scope but only used by the unit s initialization section, or at program scope and used only in the DPR file s main begin-end block, are treated by the compiler as local variables, so they re not set to all-bits-zero like their global counterparts. When you move your variable declaration to a unit but continue to use it in your DPR file, it s elevated to "global" status.
Your TGUI_Element
type has a string
member called DbgName
, and it looks like that s the only string field you have in the type hierarchy. Take that out, or change it to ShortString
, and I ll bet your crashes go away, at least temporarily.