[英]Why does my x64 program crash silently on Windows?
考虑这个小程序:
int main(int argc, char *argv[])
{
*((int *) 0) = 1;
return 0;
}
显然,写入 $0 会导致内存访问错误。 当使用 Visual C 将此程序编译为 32 位可执行文件并运行它时,Windows 7 清楚地显示该程序已崩溃:(德国系统)
然而,当使用 Visual C 将程序编译为 64 位可执行文件时,它只是默默地崩溃。 没有系统对话框弹出通知用户程序刚刚崩溃。
这是 x64 二进制文件的正常行为还是我的 Windows 7 配置有问题? 我认为操作系统应该在程序崩溃时清楚地向用户显示,而不是只是默默地杀死它们......
编辑:对于所有声称编译器可能只是优化空指针访问的人,这里是程序集。 您可以看到非法内存访问在那里,并且在运行程序后也显示在Windows的应用程序日志中。
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01
include listing.inc
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC main
; Function compile flags: /Odtp
_TEXT SEGMENT
argc$ = 8
argv$ = 16
main PROC
; File d:\test.c
; Line 2
mov QWORD PTR [rsp+16], rdx
mov DWORD PTR [rsp+8], ecx
; Line 3
mov DWORD PTR ds:0, 1 ; here we go folks
; Line 4
xor eax, eax
; Line 5
ret 0
main ENDP
_TEXT ENDS
END
编辑 2 :我还验证了HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Windows Error Reporting\\DontShowUI
设置为 0。因此 Windows 被明确配置为报告崩溃。 但它仅适用于 x86 二进制文件,不适用于 x64 二进制文件。 是的,对于 x64 二进制文件,应用程序日志中会报告崩溃,但错误对话框(请参见上面的屏幕截图)仅针对 x86 二进制文件显示,而不针对 x64 二进制文件显示,尽管DontShowUI
明确设置为 0。
编辑 3 :我在不同的 Windows 系统上进行了测试。 结果如下:
Windows 7: x86 shows crash dialog, x64 doesn't (as described above)
Windows 8: both x86 and x64 show the crash dialog
Windows 10: neither x86 nor x64 show the crash dialog
因此,这里唯一行为不一致的系统实际上是 Windows 7。在所有其他系统上,崩溃对话框要么显示要么不显示,而在 Windows 7 上,x86 和 x64 程序的崩溃之间存在不同的行为。 奇怪的。
*((int *) 0) = 1;
,因此您的整个程序都是undefined 。
各种崩溃是这种未定义行为的表现。
一些编译器可能会将您的代码优化为int main{}
:gcc 一段时间以来一直在优化高优化设置下的未定义语句。 也许这解释了 64 位编译行为?
假设发出的代码确实包含对地址零处的内存的访问,那么二进制文件就会崩溃。 Windows 不能保证显示崩溃消息——例如,它可以通过组策略来抑制。
进程本身可以使用SetErrorMode
和WerRegisterRuntimeExceptionModule
来控制它。 另见werapi.h
。
无论DontShowUI
值如何,Windows 10 上的 WER 都不会在不可见进程崩溃时显示对话框。 DontShowUI
只对显示用户界面的进程有影响。 我仔细看了看,但找不到隐形进程的类似设置。 在这些情况下,WER 的静默崩溃处理似乎是设计使然。
因此,我编写了一个工具,可以将自身挂接到 WER 并修改其行为以显示所有崩溃的对话框,包括那些在不可见进程中的崩溃: WerTweak 。 另外,它使 WER 显示与以前的 Windows 版本相同的旧式崩溃报告对话框,而不是通常在 Windows 10 中显示的残缺的新对话框。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.