我使用Peter Below's PBThreadedSplashForm在应用程序启动时显示启动窗口。
这个组件工作了10年,效果很好,但是,自从将我的 Delphi 更新到11.2后,我在CreateWindowEx调用上得到了一个AV。
这种情况仅在Win64平台上发生,在Win32上发生问题。
有谁知道这是什么原因吗?
我使用Peter Below's PBThreadedSplashForm在应用程序启动时显示启动窗口。
这个组件工作了10年,效果很好,但是,自从将我的 Delphi 更新到11.2后,我在CreateWindowEx调用上得到了一个AV。
这种情况仅在Win64平台上发生,在Win32上发生问题。
有谁知道这是什么原因吗?
1条答案
按热度按时间euoag5mw1#
由于编译器和链接器中新的默认ASLR设置,这是11.2中出现的 * 许多 * 问题之一。
快速浏览源代码后,我看到了以下内容:
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
中,而是使用本机大小的NativeInt
、Pointer
、LPARAM
或任何语义合适的指针。(禁用ASLR也会让它在“很多”情况下意外地再次工作,但这是一个非常糟糕的方法。你的软件仍然有一个非常严重的bug,随时可能表现出来。)
在您的代码中,还有