TLanguages实用程序中的Delphi访问冲突

时间:2013-03-30 21:55:18

标签: delphi delphi-7 locale

出于某种原因,尝试通过使用单例或通过直接调用构造函数来创建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

任何人都可以解释这个技巧是如何运作的,并告诉我为什么它没有按预期工作?

1 个答案:

答案 0 :(得分:4)

对于与DEP相关的较旧的Delphi版本,这似乎是一个已知问题,正如我在对该问题的评论中所猜测的那样。很明显,当启用DEP时,RTL中的代码无法工作。

以下是确认理论的链接:http://codecentral.embarcadero.com/Item/23411

虽然CodeCentral文章包含修复Delphi 5中的问题的代码,但它看起来也适用于Delphi 7。该修复程序通过挂钩SysUtils.Languages函数来工作。因此,请确保您始终使用它而不是自己调用TLanguages.Create,原因很明显。