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

TLanguages实用程序中的Delphi访问冲突,delphi,delphi-7,locale,Delphi,Delphi 7,Locale,出于某种原因,尝试使用单例或直接调用构造函数来创建SysUtils标头提供的TLanguages对象会在野外造成麻烦,有些用户会报告此错误(X不同): 。。。当执行以下看似无辜的代码行时: TLanguages.Create; 澄清一下,这与上下文无关。我可以将这一行放在我喜欢的任何地方(例如,作为空程序的唯一代码行),但问题仍然存在 奇怪的是,这个类是Delphi标准头的一部分,应该不会失败(对吧?) 构造函数试图使用一个成员函数作为EnumSystemLocales回调,这似乎是导致崩溃的

出于某种原因,尝试使用单例或直接调用构造函数来创建SysUtils标头提供的TLanguages对象会在野外造成麻烦,有些用户会报告此错误(X不同):

。。。当执行以下看似无辜的代码行时:

TLanguages.Create;
澄清一下,这与上下文无关。我可以将这一行放在我喜欢的任何地方(例如,作为空程序的唯一代码行),但问题仍然存在

奇怪的是,这个类是Delphi标准头的一部分,应该不会失败(对吧?)

构造函数试图使用一个成员函数作为EnumSystemLocales回调,这似乎是导致崩溃的原因,因为将TLanguages.LocalesCallback函数复制到全局范围并将其传递给EnumSystemLocales效果非常好

该结构包含以下Intel x86程序集,其中每个项由其操作码给定:

pop  edx
mov  eax Self
push eax
push edx
jmp  JmpOffset

有人能解释一下这个技巧是如何工作的,并告诉我为什么它没有按预期工作吗?

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

这里有一个链接来证实这一理论:


尽管那篇CodeCentral文章包含了在delphi5中修复问题的代码,但它看起来也能在delphi7中工作。修复程序通过挂接
SysUtils.Languages
函数来工作。因此,请确保您始终使用它,而不是调用
t语言。出于明显的原因,请自己创建

请包含实际的错误消息(包括地址)和一些t语言的上下文。创建;线路。那一行是在你自己的代码中,还是在其他地方?断章取义地发布一行通常对除你之外的任何人都没有意义,如果你发布的这行内容是完整的,那么它确实会导致后续的失败。谢谢。@KenWhite:错误已经存在,但是X不同(可能取决于堆的状态)。此外,环境也不是问题所在。在任何上下文中(包括其他空程序)都会发生相同的问题。这一点也得到了澄清。请提供一个简单的例子,因为目前我对你在问题中所断言的情况表示怀疑。@DavidHeffernan:下面是一个简单的例子:。不出所料,除了那句可怕的台词,它没有什么值得一提的。此外,我理解为什么这一切听起来可疑,但受影响的用户可以在任何代码上下文中完美地复制崩溃。这应该是问题所在,而不是粘贴库。而且太长了。让它成为一个控制台应用程序,你可以用大约7行代码来完成。请试着这样做。尽管如此,我无法复制。那么,发生故障的机器有什么特别之处呢?并给我们一个准确的错误信息。用实际值替换X。添加madExcept并找出AV的确切位置。我们需要尽可能多的信息。是的,DEP是问题所在。在人群中分发代码时,会遇到什么样的随机因素,这真是令人惊讶。@Orwell,这不是随机的,您的thunk不在可执行内存区域中。一旦你通过它的执行指针,DEP就会启动。+1-可怕的精神力量!(OP本可以创建一个小案例进行复制!)
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;
pop  edx
mov  eax Self
push eax
push edx
jmp  JmpOffset