I encountered an annoying bug in Visual C++ 2017 recently. It started when I found my favourite logging library, Easylogging++, output Chinese as garbage characters on Windows. Checking the documentation carefully, I noted that I should have used the macro
START_EASYLOGGINGPP. It turned out to be worse: all output starting from the Chinese character was gone. Puzzled but busy, I put it down and worked on something else.
I spend another hour of detective work on this issue today. The result was quite surprising.
- First, it is not an issue with Easylogging++. The problem can occur if I purely use
- Second, the magical thing about
START_EASYLOGGINGPPis that it will invoke
std::locale::global(std::locale("")). This is the switch that leads to the different behaviour.
- Myteriously, with the correct locale setting, I can get the correct result with both
std::wcoutand Easylogging++ in a test program. I was not able to get it working in my real project.
- Finally, it turns out that the difference above is caused by
/MD! The former (default if neither is specified on the command line) tells the Visual C++ compiler to use the static multi-threading library, and the latter (set by default in Visual Studio projects) tells the compiler to use the dynamic multi-threading library.
People may remember that I wrote about MSVCRT.DLL Console I/O Bug. While Visual C++ 2013 shows consistent behaviour between
/MD, Visual C++ 2015 and 2017 exhibit the same woeful bug when
/MD is specified on the command line. This is something perplexingly weird: it seems someone at Microsoft messed up with the MSVCRT.DLL shipped with Windows first (around 2006), and then the problem spread to the Visual C++ runtime DLL after nearly a decade!
I am using many modern C++ features, so I definitely do not want to go back to Visual C++ 2013 for new projects. It seems I have to tolerate garbage characters in the log for now. Meanwhile, I submitted a bug to Microsoft. Given that I have a bug report that is deferred for four years, I am not very hopeful. But let us wait and see.
Update (20 December 2017)
A few more tests show that the debug versions (
/MDd) both work well. So only the default release build (using the dynamic C runtime) exhibits this problem, where the executable depends on DLLs like api-ms-win-crt-stdio-l1-1-0.dll. It seems this issue is related to the Universal C Runtime introduced in Visual Studio 2015 and Windows 10. . . .