4

我注意到我的二进制文件将在没有SSE 支持的情况下在 CPU 上崩溃,并带有异常代码0xC000001D(STATUS_ILLEGAL_INSTRUCTION),尽管我正在使用 option 进行编译/arch:IA32。而且我已经能够追踪到它崩溃的确切位置:无论_snprintf_s()第一次调用哪里,它都会崩溃。崩溃在ucrtbase.dll内部,而不是我自己的代码。

现在,有趣的是,当我使用编译器选项进行“完全静态”构建时,为了避免对ucrtbase.dll/MT的显式依赖,生成的二进制文件就可以了!但是,一旦我将某些代码编译为“共享”构建,使用 option ,它将在 ucrtbase.dll中再次崩溃。/MD

所以看起来UCRT的“静态”版本仍然可以在没有SSE支持的CPU上工作,但“共享”(DLL)版本不能。这种不一致对我来说显然是一个错误!

有什么想法吗?


搭建环境:

  • 视窗 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;
}
4

1 回答 1

3

更新:

经过更多的调试和摆弄,我做了一个非常有趣的观察: 最新 vcredist_x86.exe的(Microsoft Visual C++ 2017 Redistributable 安装程序)中包含的 UCRT“Redist”DLL,即 VS2017.8 (v14.15.26706) 附带的版本,是实际上与可以在最新Windows SDK (v10.0.17134.12)Redist\ucrt\DLLs\x86目录中找到的那些 UCRT“Redist”DLL 完全不同:

  • ucrtbase.dll最新的Windows SDK
    v10.0.17134.12

  • ucrtbase.dll来自最新的Visual C++ 2017 Redistributable 安装程序:
    v10.0.10586.15

事实上,我现在可以确认,使用最新的Visual C++ 2017 (v14.15.26706) 编译的应用程序并使用该/MD选项在SSE CPU 上正常工作,只要我们使用从最新安装程序ucrtbase.dll中提取的“旧”版本. vcredist_x86.exe

如果 Windows SDK 已经提供了更新的版本,我有点担心使用这样一个旧版本的 UCRT。但是,显然,这就是微软使用 Visual C++ 2017 Redistributable 安装程序所做的事情。所以,我想,这是我们应该使用的......


以防万一微软的任何人正在阅读此内容:

如果在Windows SDK 的目录中,UCRT 的每个“化身”(UCRT 的最新“尖端”版本)都有单独的子文件夹,那么对于软件开发人员来说,事情可能不会那么混乱和容易出错Redist\ucrt以及我们实际上应该重新分发的 UCRT 的“兼容”版本。如果Microsoft 的某个人花三分钟时间编写一个小 README 文件,告诉我们应该选择 CRT 的哪个“化身”并将其放在Redist\ucrt\README.txt,那么几乎不可能做错......

于 2018-08-26T14:20:06.227 回答