【发布时间】:2018-08-26 11:34:44
【问题描述】:
我注意到我的二进制文件将在 CPU 上崩溃没有 SSE 支持,异常代码 0xC000001D (STATUS_ILLEGAL_INSTRUCTION),尽管我使用选项 /arch:IA32 进行编译。而且我已经能够追踪到它崩溃的确切位置:第一次调用 _snprintf_s() 时,它就会崩溃。崩溃发生在 ucrtbase.dll 内部,不是我自己的代码。
现在,有趣部分是,当我使用编译器选项 /MT 进行“完全静态”构建时,以避免显式依赖 ucrtbase.dll,生成的二进制文件就可以了!但是,一旦我使用选项 /MD 将某些代码编译为“共享”构建,它将在 ucrtbase.dll 中再次崩溃。
所以看起来 UCRT 的“静态”版本仍然可以在 CPU 上运行 SSE 支持,但是“共享" (DLL) 版本可以。这种不一致对我来说显然是个错误!
有什么想法吗?
构建环境:
- Windows 10 v1803
- Visual Studio 2017.8 (v15.8.1)
- Windows SDK v10.0.17134.12
- 工具集:
v141_xp - 编译器选项:
/arch:IA32
测试机(仅用于兼容性测试):
- CPU:奔腾 II
- 操作系统:带有 Service-Pack 3 的 Windows XP
注意: 用于设置“共享”构建的 Redist DLL (ucrtbase.dll +api-ms-win-*.dll) 已直接从 C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86 目录复制!据我所知,这是这些 DLL 的最新可用版本 (v10.0.17134.12)。
即使是这个最小的测试程序也会重现崩溃:
#include <stdio.h>
int main()
{
char buffer[128];
_snprintf_s(buffer, 128, _TRUNCATE, "Hello %s!\n", "World!");
fputs(buffer, stdout);
getc(stdin);
return 0;
}
【问题讨论】:
-
我已经用调试器追踪了。它在
_snprintf_s()的实现内部崩溃,在系统 DLLucrtbase.dll内部崩溃。代码是 STATUS_ILLEGAL_INSTRUCTION,所以几乎可以肯定 不是我的代码中的问题,而是在系统 DLLucrtbase.dll内的预先存在的代码中使用 SSE 指令。即使是带有 nothing 但main()调用_snprintf_s()的最小测试应用程序也会重现崩溃!并且仅在 CPU 没有 SSE 上;否则它工作正常! -
你试过standard
snprintf()吗?如果你可以使用 C++11,它是可用的。 -
您也应该将此情况报告给 Microsoft。
-
@KhouriGiordano 他们可能会告诉 OP,Windows XP 支持已于 2014 年结束,并且什么也不做。截至今天,所有受支持的 Windows 版本(即 8.1 和 10)都需要 SSE。
-
@SkepticalEmpiricist:调用
snprintf()会导致与调用_snprintf_s()相同的崩溃。查看调用堆栈,似乎它们都在ucrtbase.dll内部名为_stdio_common_vsprintf的同一个内部例程中结束 - 它崩溃了。
标签: c++ visual-c++ visual-studio-2017 universal-crt