【发布时间】:2019-03-14 01:31:10
【问题描述】:
考虑这个小程序:
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。
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
因此,这里唯一表现不一致的系统实际上是 Windows 7。在所有其他系统上,崩溃对话框要么显示要么不显示,而在 Windows 7 上,x86 和 x64 程序的崩溃之间的行为不同。很奇怪。
【问题讨论】:
-
“这是正常行为吗”,再次询问未定义行为的行为没有意义。 “显然,写入 $0 会导致内存访问错误。”不,那个未定义的行为。
-
@Stargateur 即使它在技术上是 UB,在 Windows 上它应该在 x86 和 x64 中崩溃,因为它应该在 Linux 上崩溃
-
那是 WER 对话框,它是否显示是操作系统配置选项。顺便说一句,它在 Win10 机器上不再默认了。仔细检查您在应用程序日志中是否收到了崩溃事件。在 superuser.com 上询问 WER 配置。并考虑继续前进,您要确保调试器可以帮助您诊断此错误。
-
@Stargateur:从编程语言的角度来看,你是对的:思考展示 UB 的代码的潜在结果是没有实际意义的。但是,平台可以将保证扩展到编程语言所建立的保证之外。在 Windows(以及任何针对 Windows 的编译器)上,取消引用指向无效地址的指针将确定性地触发访问冲突,报告为 SEH 异常。因此,问题中的代码就语言而言表现出 UB,但在 Windows 上仍会表现出明确定义的行为。
-
@sta:引发 SEH 异常以响应对不可访问内存的写入或读取是 Windows ABI 的一部分。 任何面向 Windows 的编译器必须实现该协定。我在之前的评论中明确地说 “平台” 是指操作系统和编译器的组合。这不仅限于 Visual Studio。此外,指向堆栈的指针始终有效。堆栈内存是可访问的。它可能不是指向正确地址的指针,但这并不意味着操作系统、运行时或编译器需要引发 SEH 异常。您在这里混淆了不同的方面。
标签: c windows crash windows-7-x64 undefined-behavior