microsoft / STL

MSVC's implementation of the C++ Standard Library.
Other
9.93k stars 1.45k forks source link

basic_ostream<unsigned char>: Crash at initialization on Arm64 architecture with Clang compiler and STL version 16.9.4 #1887

Open arthurbiancarelli opened 3 years ago

arthurbiancarelli commented 3 years ago

Describe the bug Instantiating a derived class from basic_ostream using unsigned char as the character type results in a access violation when compiling with Clang. Crash occurs in the init method of std::basic_ios when accessing the ctype of the std::_Locinfo class (init calls widen then use_facet, etc...)

Command-line test case

#include <iostream>
#include <sstream>

template <class CharT, class Traits = std::char_traits<CharT>>
struct Stream : public std::basic_ostream<CharT, Traits> {
    Stream() : std::basic_ostream<CharT, Traits>(&buffer) {
    }
    std::basic_stringbuf<CharT, Traits> buffer;
};

int main() {
    {
        // OK
        Stream<char> stream;
        // Prevent optimization
        std::cout << &stream << std::endl;
    }
    {
        // KO
        Stream<unsigned char> stream;
        // Prevent optimization
        std::cout << &stream << std::endl;
    }
    return 0;
}
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\x64\bin\clang-cl.exe /c /nologo /W1 /WX- /diagnostics:column /O2 /Ob2 
  /D WIN32 /D _WINDOWS /D NDEBUG /D "CMAKE_INTDIR=\"Release\"" /D _MBCS /EHsc /MD /GS /fp:precise /GR /Fo"TestArmStd.dir\Release\\" /Gd /TP --target 
  =arm64-pc-windows-msvc  C:\Users\ARTHUR\Documents\code\TestArmStd\main.cpp
Link:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\Llvm\x64\bin\lld-link.exe /OUT:"C:\Users\ARTHUR\Documents\code\TestArmStd\b
  uild-clang-arm64-windows\Release\TestArmStd.exe" /INCREMENTAL:NO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib 
   uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:"C:/Users/ARTHUR/Documents/co 
  de/TestArmStd/build-clang-arm64-windows/Release/TestArmStd.pdb" /SUBSYSTEM:CONSOLE /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/Users/ARTHUR/Documents/code/ 
  TestArmStd/build-clang-arm64-windows/Release/TestArmStd.lib"   /machine:ARM64 TestArmStd.dir\Release\main.obj
  TestArmStd.vcxproj -> C:\Users\ARTHUR\Documents\code\TestArmStd\build-clang-arm64-windows\Release\TestArmStd.exe

Expected behavior This code should not crash

STL version

Microsoft Visual Studio Community 2019
Version 16.9.4

Additional context Hope this is the good place to report this, that this code is valid and that I'm using the correct compile options for ClangCl. Please note that this crash does not occur with MSVC compiler. I'm cross-compiling this code on a x64 Host and deploying it on a fresh Windows installation (Windows 10 Professional, Build 21364.1 emulated on a mac M1 hardware) using the Visual Studio remote debugger.

CaseyCarter commented 3 years ago

Thanks, @arthurbiancarelli - this is probably as good a place as any.

Given that this works with MSVC on ARM64 (per the report) and Clang targeting both x86 and x64 (I verified), I suspect the root cause is an issue with Clang's implementation of the MS ABI on ARM64. We'll need to reduce this repro and make it library-free to prove that's the case, at which time we can report the bug to our Clang friends and (hopefully) devise a workaround.

arthurbiancarelli commented 3 years ago

I tried to reduce the example a bit, did not succeed without the library though:

#include <xlocale>

struct ctype : std::ctype<unsigned char> {
};

int main() {
    ctype type; // Crash on destruction; access violation when freeing _Ctype._LocaleName 
    return 0;
}

I think you're right that it is an ABI issue or related because I just found out the original example (or this one) does not crash when I link to the static version of the C++ runtime