Delphi 11.2:CreateWindowEx在x64上执行线程失败

yacmzcpb  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(121)

我使用Peter Below's PBThreadedSplashForm在应用程序启动时显示启动窗口。
这个组件工作了10年,效果很好,但是,自从将我的 Delphi 更新到11.2后,我在CreateWindowEx调用上得到了一个AV。
这种情况仅在Win64平台上发生,在Win32上发生问题。
有谁知道这是什么原因吗?

euoag5mw

euoag5mw1#

由于编译器和链接器中新的默认ASLR设置,这是11.2中出现的 * 许多 * 问题之一。
快速浏览源代码后,我看到了以下内容:

SetWindowLong( wnd, GWL_WNDPROC, Integer( thread.FCallstub ));

thread.FCallstub被定义为Pointer
正如我所料。
您可以看到,指针是原生大小,因此在32位应用程序中,指针是32位宽,而在64位应用程序中,指针是64位宽。
在32位世界中,指针值被临时保存在Integer中是很常见的。这是因为32位指针适合32位Integer
但在64位应用程序中,这是一个明显的bug,因为64位指针不适合32位Integer,这就像取一个电话号码5362417812,并将其截断为17812,希望它仍然“工作”。
当然,一般来说,这会导致AV和内存损坏等bug。
然而,直到最近,64位 Delphi 应用程序中的指针“偶然”不使用其32个高位的可能性还是相当高的(因此它可能是$0000000000A3BE41,因此将其截断为$00A3BE41没有任何效果)。因此,它似乎在大多数时间都能工作,但只是偶然。
现在, Delphi 编译器和链接器的最新版本启用了ASLR,使得此类事故的可能性大大降低。
而这是一件好事:如果您的代码中有严重的错误,最好立即发现,而不是“随机”地向客户报告。
因此,要解决这个问题,您需要仔细检查代码,确保永远不要将指针存储在32位Integer中,而是使用本机大小的NativeIntPointerLPARAM或任何语义合适的指针。
(禁用ASLR也会让它在“很多”情况下意外地再次工作,但这是一个非常糟糕的方法。你的软件仍然有一个非常严重的bug,随时可能表现出来。)
在您的代码中,还有

Integer( Pchar( FStatusMessage ))
Integer( Pchar( msg ))

相关问题