It was brought to my attention that my binary will crash on the CPU without SSE support, with exception code 0xC000001D
(STATUS_ILLEGAL_INSTRUCTION), despite I'm compiling with option /arch:IA32
. And I have been able to track down the exact place where it crashes: Wherever _snprintf_s()
is called for the first time, it will crash. The crash is inside of ucrtbase.dll, not my own code.
Now, the interesting part is that, when I make a "fully static" build with compiler option /MT
, so to avoid explicity dependency on ucrtbase.dll, the resulting binary works just fine! But, as soon as I compile the exactly some code as "shared" build, with option /MD
, it will crash again in ucrtbase.dll.
So it would appear that "static" version of the UCRT still can work on the CPU without SSE support, but the "shared" (DLL) version can not. This inconsistency would clearly seem like a bug to me!
Any thoughts?
Build environment:
- Windows 10 v1803
- Visual Studio 2017.8 (v15.8.1)
- Windows SDK v10.0.17134.12
- Toolset:
v141_xp
- Compiler option:
/arch:IA32
Test machine (used for compat-testing only):
- CPU: Pentium II
- OS: Windows XP with Service-Pack 3
Note: Redist DLLs (ucrtbase.dll
+api-ms-win-*.dll
) for the setup of the "shared" build have been copied straight from C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86
directory! To the best of my knowledge, this is the latest available version of these DLLs (v10.0.17134.12).
Even this minimal test program will reproduce the crash:
#include <stdio.h>
int main()
{
char buffer[128];
_snprintf_s(buffer, 128, _TRUNCATE, "Hello %s!\n", "World!");
fputs(buffer, stdout);
getc(stdin);
return 0;
}