为什么我的x64程序在Windows上无提示地崩溃?

时间:2018-10-09 09:55:23

标签: c windows crash windows-7-x64 undefined-behavior

考虑这个小程序:

int main(int argc, char *argv[])
{
    *((int *) 0) = 1;
    return 0;
}

显然,写入$ 0会导致内存访问错误。当使用Visual C将程序编译为32位可执行文件并运行该程序时,Windows 7清楚地表明该程序已崩溃:(德语系统)

Screenshot

但是,当使用Visual C将程序编译为64位可执行文件时,它只是崩溃而已。没有弹出系统对话框,通知用户程序刚刚崩溃。

这是x64二进制文件的正常行为,还是我的Windows 7配置有问题?我认为,当程序崩溃时,操作系统应该向用户清楚显示,而不是无声地杀死它们...

EDIT :对于所有声称编译器可能只是优化空指针访问权限的人来说,这就是程序集。您可以看到其中存在非法内存访问,并且在运行该程序后,该错误也显示在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

EDIT 2 :我还验证了HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI设置为0。因此Windows已明确配置为报告崩溃。但这仅适用于x86二进制文件,而不适用于x64二进制文件。是的,对于x64二进制文件,崩溃是在应用程序日志中报告的,但是错误对话框(请参见上面的屏幕快照)仅针对x86二进制文件而不是x64二进制文件显示,尽管DontShowUI明确设置为0。

EDIT 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

因此,唯一行为不一致的系统实际上是Windows7。在所有其他系统上,是否显示崩溃对话框,而在Windows 7上,x86和x64程序崩溃的行为有所不同。很奇怪。

3 个答案:

答案 0 :(得分:2)

*((int *) 0) = 1;以及整个程序的行为是未定义

各种崩溃是这种不确定行为的体现。

某些编译器可能会将您的代码优化到int main{}:一段时间以来,gcc一直在高优化设置上优化未定义的语句。也许这就是64位编译行为的原因?

答案 1 :(得分:2)

假设发出的代码确实包含对地址为零的内存的访问,那么二进制文件将崩溃。 Windows不能保证显示崩溃消息-例如,可以是suppressed via group policy

进程本身可以使用SetErrorModeWerRegisterRuntimeExceptionModule进行控制。另请参见werapi.h

答案 2 :(得分:0)

Windows 10上的WER不会在看不见的进程崩溃时显示对话框,而不管DontShowUI的值如何。 DontShowUI仅对显示用户界面的进程有影响。我看上去很努力,但找不到隐形进程的类似设置。在这些情况下,WER的无声崩溃处理似乎是设计使然。

因此,我编写了一个工具,该工具将自己挂接到WER中并修改其行为以显示所有崩溃的对话框,包括不可见进程中的崩溃:WerTweak。另外,它使WER显示与以前的Windows版本相同的旧式崩溃报告对话框,而不是通常在Windows 10中显示的残缺的新对话框。