我正在尝试使用boost库为我的字符串类提供i18支持。 我使用的是Microsoft Visual Studio编译器VC10和64位Windows 7机器。
我能够使用boost库编译和链接我的应用程序,但是我的应用程序在调用boost :: locale :: to_upper()时崩溃。
以下是我写的代码。
#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
}
崩溃发生在以下函数中。此函数抛出错误的强制转换异常。
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
....
....
....
}
你能帮我解决吗?
此致 萨米特
答案 0 :(得分:10)
在Windows 7 64位的Visual Studio 2008应用程序中使用Boost 1.55的静态库构建时,我遇到了同样的问题,其中主可执行文件和几个DLL都链接到Boost。我不确定你的问题是否与我的相同,因为你没有提到使用DLL,但当我第一次开始调查时,这并不是我认为相关的东西。
如果您只是对最直接的解决方法感兴趣,那么将Boost构建为共享库就应该这样做。具体来说,我的意思是将b2命令行的link
属性设置为shared
而不是static
。
使用静态库构建的原因有一个问题是由于Boost.Locale使用std::locale::facet
对象进行文本转换操作,如上限和规范化。 std::locale::facet
类需要具有id
静态成员变量,其标准库实现在静态初始化期间构造时,其唯一值将分配。
使用静态库时的问题是所有可执行文件和DLL都从静态库中获取自己的静态成员变量的不同副本,如Shared global variable in C++ static library中所述。当您使用boost::locale::generator::operator()
生成语言环境时,它只会将std::locale::facet
个对象安装到具有id
成员变量的语言环境中,该成员变量是包含该调用的同一DLL或可执行文件的一部分
正如我上面所说,最直接的解决方法是将Boost构建为共享库。那样只会有一个副本Boost.Locale的静态成员变量。具体来说,它们将位于Boost.Locale DLL中。
您可以通过确保所有DLL中的所有std::locale::facet
对象和使用Boost.Locale的可执行文件安装到您尝试的std::locale
对象中,来构建Boost的静态库。使用
您可以使用下面的代码来执行此操作。对于DLL,当第二个参数DllMain
为fdwReason
时,您可以在DLL_PROCESS_ATTACH
中调用它,对于您的可执行文件,您可以在WinMain
或其他一些应用程序入口点调用它(如果您使用的是MFC或Qt之类的东西)。
void setup_global_locale()
{
const boost::locale::generator generator;
const std::locale locale = generator.generate( std::locale(), "" );
std::locale::global( locale );
}
代码的重要部分是它每次运行时都使用全局语言环境作为基本语言环境,并将新生成的语言环境安装为新的全局语言环境。这与boost::locale::generator::operator()
将执行的操作不同,因为它使用std::locale::classic
作为基本语言环境,并且无法修改该语言环境。通过从每个DLL和可执行文件中调用它,您可以将每个std::locale::facet
对象安装到全局区域设置中。