Reputation: 577
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:
v141_xp
/arch:IA32
Test machine (used for compat-testing only):
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;
}
Upvotes: 4
Views: 2604
Reputation: 577
Update:
After some more debugging and fiddling around, I made a very interesting observation: The UCRT "Redist" DLLs contained within the latest vcredist_x86.exe
(Microsoft Visual C++ 2017 Redistributable installer), i.e. the version that ships with VS2017.8 (v14.15.26706), are actually quite different from those UCRT "Redist" DLLs that can be found in the Redist\ucrt\DLLs\x86
directory of the latest Windows SDK (v10.0.17134.12):
ucrtbase.dll
from latest Windows SDK
v10.0.17134.12
ucrtbase.dll
from latest Visual C++ 2017 Redistributable installer:
v10.0.10586.15
Indeed, I can confirm now that the application compiled with latest Visual C++ 2017 (v14.15.26706) and using the /MD
option works correctly on the non-SSE CPU, as long as we use the "old" ucrtbase.dll
version, as extracted from the latest vcredist_x86.exe
installer.
I'm a bit concerned using such an old version of the UCRT, if the Windows SDK already provides a much newer version. But, apparently, that is what Microsoft is doing themselves with the Visual C++ 2017 Redistributable installer. So, I guess, it is what we are supposed to use...
Just in case anybody at Microsoft is reading this:
Things could have been way less confusing and error-prone for software developers, if, in the Redist\ucrt
directory of the Windows SDK, there were separate sub-folders for each "incarnation" of the UCRT – the latest "cutting edge" version of the UCRT and the "compatible" version of the UCRT that we are actually supposed to redistribute. If then somebody at Microsoft spent three minutes for writing a little README file that tells us which "incarnation" of the CRT we should pick and put it at Redist\ucrt\README.txt
, it would be almost impossible to do wrong...
Upvotes: 3