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