由于某些原因,尝试使用单例或直接调用构造函数创建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
有没有人能解释一下这个技巧是如何工作的并告诉我为什么它不能按预期工作?