Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::filesystem, std::getenv and concurrency

Suppose that I have the following code:

#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>

void foo()
{
  const boost::filesystem::wpath& appdata_folder = std::getenv("APPDATA");
  while (true)
  {
    boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  }
}

int main()
{
  boost::thread first(foo);
  boost::thread second(foo);

  first.join();
  second.join();
}

It fails at run-time with the following error:

* Internal Program Error - assertion (codecvt_facet_ptr()) failed in const class std::codecvt &__cdecl boost::filesystem::path::codecvt(void): libs\filesystem\src\path.cpp(888): codecvt_facet_ptr() facet hasn't been properly initialized

In the documentation I read that it's not thread-safe in terms of parallel set and get operations, not the several get operations as in my case. _wgetenv function works the same way.

Why? What am I doing wrong?

MSVC-12.0, boost 1.55, Windows 8

Thanks in advance.

like image 352
FrozenHeart Avatar asked Oct 21 '22 02:10

FrozenHeart


1 Answers

There seem to be bug reports around this for some versions of VS and boost: e.g. here

The suggestion is to initialise before your threads:

void make_loc(std::locale& loc)
{
    loc = default_locale();
}

int main()
{
    std::locale loc;

    boost::once_flag once;
    boost::call_once(once, boost::bind(&make_loc, boost::ref(loc)));
    //as you were
}
like image 132
doctorlove Avatar answered Oct 30 '22 00:10

doctorlove