我使用彼得·下面的PBThreadedSplashForm在应用程序启动期间显示一个启动窗口。
这个组件工作了10年,但是,自从我的Delphi升级到11.2,我就可以在CreateWindowEx上得到一个AV。
这只发生在Win64平台上,在Win32上的问题上。
有谁知道是什么原因造成的?
发布于 2022-11-20 12:56:34
由于编译器和链接器中新的默认ASLR设置,这是11.2中出现的许多问题之一。
在非常快速地浏览了源代码之后,我看到了以下内容:
SetWindowLong( wnd, GWL_WNDPROC, Integer( thread.FCallstub ));
thread.FCallstub
被定义为Pointer
。
正如本人所料的。
你看,指针是原生大小的,所以在32位应用程序中,指针是32位宽,而在64位应用程序中,指针是64位宽。
在32位世界中,指针值临时保存在Integer
中是非常常见的,这是因为32位指针适合32位Integer
。
但是在64位应用程序中,这是一个明显的错误,因为64位指针不适合32位Integer
。这就像拿5362417812这样的电话号码,把它截短到17812,希望它还能“工作”。
当然,通常情况下,这会导致诸如AVs和内存损坏之类的错误。
然而,直到最近,64位Delphi应用程序中的指针“偶然”没有使用它的32位(所以可能是$0000000000A3BE41
,因此将指针截断到$00A3BE41
中没有任何效果)的可能性很大。因此,它似乎大部分时间起作用,但只是偶然的。
现在,Delphi编译器和链接器的最新版本启用了ASLR,从而大大降低了此类事故的可能性。
这是一件好事:如果您的代码中有一个严重的错误,最好是立即发现它,而不是“随机地”访问您的客户。
因此,要解决这个问题,您需要遍历代码,并确保从未将指针存储在32位Integer
中。相反,使用本机大小的NativeInt
、Pointer
、LPARAM
或任何语义上合适的东西。
(禁用ASLR也将使其在“许多”情况下再次发生意外,但这是一个非常糟糕的方法。您的软件仍然有一个非常严重的错误,随时都可能出现。)
在您的代码中,也有
Integer( Pchar( FStatusMessage ))
Integer( Pchar( msg ))
https://stackoverflow.com/questions/74508190
复制相似问题