古いスタイルの Delphi オブジェクトは、Delphi 2 のリリース以降、おそらくそれ以前に壊れています。string
または動的配列などのコンパイラ管理型のフィールドがある場合、継承はうまくいきません。2004 年にcomp.lang.pascal.delphi.miscでそれについての議論がありました。これを再現するコードは次のとおりです。
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;
そして実際にTBase
は、関数のプロローグ コードがたまたま生成される方法のため、偶然にのみ問題ありません。その関数に追加のコードを入れると、とにかくクラッシュする可能性があります。
実際、これはまさにあなたが観察したとおりです — 古いスタイルのオブジェクトは適切に初期化されません。それらの文字列フィールドは、最初から空の文字列を保持していません。代わりに、それらはガベージを保持するため、 のようなものを使用せずにそれらを自分で初期化することさえできませんFillChar
.
これは、変数がローカル変数であるためと思われます。ユニット スコープ (「グローバル」) 変数は問題なく動作するようです。ユニット スコープで宣言されているがユニットの初期化セクションでのみ使用される変数、またはプログラム スコープで DPR ファイルのメイン begin-end ブロックでのみ使用される変数は、コンパイラによってローカル変数として扱われるため、すべての変数には設定されません。 -bits-zero はグローバル版と同様です。変数宣言をユニットに移動しても、DPR ファイルで引き続き使用すると、「グローバル」ステータスに昇格します。
あなたのTGUI_Element
タイプには というstring
メンバーがDbgName
あり、それがタイプ階層にある唯一の文字列フィールドのようです。それを削除するか、に変更するとShortString
、少なくとも一時的にクラッシュがなくなるはずです。