I am trying to use boost library for providing i18 support to my string class. I am using Microsoft Visual studio compiler VC10 and 64 bit Windows 7 machine.
I am able to compile and link my application with the boost library however my application crashes while invoking boost::locale::to_upper().
Following is the code I wrote.
#include <boost/locale.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/system/config.hpp>
String::MakeUpper()()
{
boost::locale::generator gen;
std::locale loc = gen("");
std::locale::global(loc);
std::string str2 = boost::locale::to_upper("001Öä", loc); // application crashes here.
std::string str3 = boost::locale::to_upper("001Öä"); // This also does not work
}
The crash happens in the following function. this function throws bad cast exception.
template<class _Facet> inline
const _Facet& __CRTDECL use_facet(const locale& _Loc)
{ // get facet reference from locale
_BEGIN_LOCK(_LOCK_LOCALE) // the thread lock, make get atomic
const locale::facet *_Psave =
_Facetptr<_Facet>::_Psave; // static pointer to lazy facet
size_t _Id = _Facet::id;
const locale::facet *_Pf = _Loc._Getfacet(_Id);
if (_Pf != 0)
; // got facet from locale
else if (_Psave != 0)
_Pf = _Psave; // lazy facet already allocated
else if (_Facet::_Getcat(&_Psave, &_Loc) == (size_t)(-1))
#if _HAS_EXCEPTIONS
_THROW_NCEE(bad_cast, _EMPTY_ARGUMENT); // lazy disallowed
....
....
....
}
Could you please help me out.
Regards, Sumit
I had this same issue when using a static library build of Boost 1.55 in a Visual Studio 2008 application on Windows 7 64-bit where both the main executable and a couple DLLs all linked to Boost. I'm not sure if your issue is the same as mine since you didn't mention using DLLs, but that wasn't something I thought was relevant when I first started investigating this.
If you're just interested in the most straight-forward way to fix this, then building Boost as a shared library should do it. Specifically, I mean setting the
link
property of the b2 command-line toshared
rather thanstatic
.Explanation
The reason using a static library build has a problem is due to Boost.Locale using
std::locale::facet
objects for doing its text conversion operations like upper-casing and normalizing.std::locale::facet
classes are required to have anid
static member variable whose unique value is assigned by the Standard Library implementation when it is constructed during static initialization.The problem with this when using a static library is that all executables and DLLs get their own distinct copy of static member variables from a static library, as discussed in Shared global variable in C++ static library. When you use
boost::locale::generator::operator()
to generate a locale, it only installs thestd::locale::facet
objects into the locale that have anid
member variable that is part of the same DLL or executable where that call is contained.As I said above, the most straight-forward way to fix this is to build Boost as a shared library. That way there will only be one copy Boost.Locale's static member variables. Specifically, they'll be in the Boost.Locale DLL.
Alternative Solution
You can do this with a static library build of Boost by making sure all of
std::locale::facet
objects from all DLLs and the executable using Boost.Locale get installed into thestd::locale
object you're trying to use.You can use some code like below to do this. For DLLs, you could call this in
DllMain
when its second parameterfdwReason
isDLL_PROCESS_ATTACH
, and for your executable, you could call it inWinMain
or some other application entry point (if you're using something like MFC or Qt).The important piece of the code is that it's using the global locale as the base locale each time it's run, and it installs the newly-generated locale as the new global locale. This is different from what
boost::locale::generator::operator()
will do, since it usesstd::locale::classic
as the base locale, and that one cannot be modified. By calling this from each DLL and the executable, you'll install each of theirstd::locale::facet
objects into the global locale.