何らかの理由で、sysUtils ヘッダーによって提供される TLanguages オブジェクトをシングルトンを使用するか、コンストラクターを直接呼び出して作成しようとすると、実際に問題が発生し、一部のユーザーがこのエラーを報告します (X は異なります)。
Access violation at address X. Write of address X (at address X)
...次の一見無害なコード行が実行されると:
TLanguages.Create;
明確にするために、これはコンテキストとは関係ありません。この行を好きな場所 (たとえば、空のプログラムの唯一のコード行) に配置できますが、問題は残ります。
奇妙な点は、このクラスが失敗しないはずの Delphi の標準ヘッダーの一部であることです (そうですか?)。
constructor TLanguages.Create;
type
TCallbackThunk = packed record
POPEDX: Byte;
MOVEAX: Byte;
SelfPtr: Pointer;
PUSHEAX: Byte;
PUSHEDX: Byte;
JMP: Byte;
JmpOffset: Integer;
end;
var
Callback: TCallbackThunk;
begin
inherited Create;
Callback.POPEDX := $5A;
Callback.MOVEAX := $B8;
Callback.SelfPtr := Self;
Callback.PUSHEAX := $50;
Callback.PUSHEDX := $52;
Callback.JMP := $E9;
Callback.JmpOffset := Integer(@TLanguages.LocalesCallback) - Integer(@Callback.JMP) - 5;
EnumSystemLocales(TFNLocaleEnumProc(@Callback), LCID_SUPPORTED);
end;
コンストラクターはメンバー関数を EnumSystemLocales コールバックとして使用しようとしますが、これがクラッシュの原因になっているようです。これは、TLanguages.LocalesCallback関数をグローバル スコープにコピーし、それを EnumSystemLocales に渡すと問題なく動作するためです。
構造体には次の Intel x86 アセンブリが含まれており、各項目はオペコードによって指定されます。
pop edx
mov eax Self
push eax
push edx
jmp JmpOffset
トリックがどのように機能するかを説明し、期待どおりに機能しない理由を教えてもらえますか?