Opened 11 years ago

Closed 11 years ago

#6690 closed Bugs (fixed)

access violation using global path object

Reported by: Claudio Bley Owned by: Beman Dawes
Milestone: To Be Determined Component: filesystem
Version: Boost 1.49.0 Severity: Regression
Keywords: Cc:

Description

I think this is an instance of "static initialization order fiasco".

The following code crashes with "Access violation reading location 0x00000000".

#include <boost/filesystem.hpp>
#include <iostream>

const boost::filesystem::path p("test");

int main(int argc, char *argv[])
{
  std::cout << p << std::endl;
}

This is caused by codecvt_facet not being initialised on its first use. Call Stack:

fspath.exe!std::codecvt<wchar_t,char,int>::in(int & _State, const char * _First1, const char * _Last1, const char * & _Mid1, wchar_t * _First2, wchar_t * _Last2, wchar_t * & _Mid2)  Line 1521 + 0x1f bytes	C++
fspath.exe!`anonymous namespace'::convert_aux(const char * from, const char * from_end, wchar_t * to, wchar_t * to_end, std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & target, const std::codecvt<wchar_t,char,int> & cvt)  Line 84 + 0x24 bytes	C++
fspath.exe!boost::filesystem3::path_traits::convert(const char * from, const char * from_end, std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & to, const std::codecvt<wchar_t,char,int> & cvt)  Line 165 + 0x20 bytes	C++
fspath.exe!boost::filesystem3::path_traits::dispatch<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > >(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & c, std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & to, const std::codecvt<wchar_t,char,int> & cvt)  Line 174 + 0x60 bytes	C++
fspath.exe!boost::filesystem3::path::path<char const [5]>(const char [5]& source, void * __formal)  Line 135 + 0x23 bytes	C++

this == 0x00000000

Compiled with cl /EHsc /DEBUG /Zi /D _DEBUG /MTd /I%localappdata%\boost\boost_1_49 fspath.cpp /link /libpath:%localappdata%\boost\boost_1_49\lib.

  • Claudio

Change History (3)

comment:1 by mjklaim@…, 11 years ago

After some hunting:

  • path::wchar_t_codecvt_facet() always return null
  • the current implementation of this function is supposed to create/initialize the object it will return;
  • the current implementation doesn't create/initialize this object if it's not an Apple context (not sure what the macros means here) so any other platform will just return the object pointer without any initialization, that is, undefined behaviour, meaning the pointer is null in debug.
  • in the case of windows, the object should have been initialized before the function call, as it is defined (in path.cpp) :
#ifdef BOOST_WINDOWS_API

  std::locale path_locale(std::locale(), new windows_file_codecvt); 

  const std::codecvt<wchar_t, char, std::mbstate_t>*
    codecvt_facet(&std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
      (path_locale));

I suppose that an assertion checking the pointer in path::wchar_t_codecvt_facet() implementation would be helpful for tests.

I don't have time to go farther, but my understanding is that either:

  • the object creation returns null (that would be surprising though)
  • the object creation never occurs.

For this last point, I think that it would be good to check that the compiled code is not the "all posix" one:


#else  // Other POSIX

  // ISO C calls std::locale("") "the locale-specific native environment", and this
  // locale is the default for many POSIX-based operating systems such as Linux.

  // std::locale("") construction can throw (if environmental variables LC_MESSAGES or
  // or LANG are wrong, for example), so lazy initialization is used to ensure
  // that exceptions occur after main() starts and so can be caught.

  std::locale path_locale;  // initialized by path::wchar_t_codecvt_facet() below
  const std::codecvt<wchar_t, char, std::mbstate_t>* codecvt_facet;  // ditto

# endif

Assuming you add an assertion in the function implementation, setting this variable to null would then be very helpful in tests too.

I think I'll have to switch back to the previous boost version for now but I hope you can fin the problem.

comment:2 by Beman Dawes, 11 years ago

Status: newassigned

I'm working this issue today. Plan is to (1) revert 76303 and verify that fixes the initialization problems, and then (2) work on fixes to #4889, #6320, codecvt_facet not thread safe on Windows, which will be reintroduced when 76303 is reverted.

--Beman

comment:3 by Beman Dawes, 11 years ago

Resolution: fixed
Status: assignedclosed

(In [78000]) Fix #6690 and #6737, resolving static linking related problems with VC++ 8 through 11. Note that this fix may reintroduce codecvt thread safety problems #4889, #6320, for these compilers if static linking is used.

Note: See TracTickets for help on using tickets.