C++ C++;boost在使用区域设置时崩溃

C++ C++;boost在使用区域设置时崩溃,c++,boost,crash,locale,C++,Boost,Crash,Locale,我试图使用boost库为我的string类提供i18支持。 我正在使用Microsoft Visual studio编译器VC10和64位Windows 7计算机 我能够编译我的应用程序并将其链接到boost库,但是我的应用程序在调用boost::locale::to_upper()时崩溃 以下是我编写的代码 #include <boost/locale.hpp> #include <boost/algorithm/string/case_conv.hpp> #inclu

我试图使用boost库为我的string类提供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
    }
#包括
#包括
#包括
字符串::MakeUpper()()
{
boost::locale::gen生成器;
std::LOCE loc=gen(“”);
std::locale::global(loc);
std::string str2=boost::locale::to_upper(“001Öä”,loc);//应用程序在此崩溃。
std::string str3=boost::locale::to_upper(“001ä”);//这也不起作用
}
崩溃发生在以下函数中。此函数引发错误强制转换异常

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

....
....
....

}
模板内联
常量方面和CRTDECL使用方面(常量区域设置和位置)
{//从区域设置获取方面引用
_BEGIN\u LOCK(\u LOCK\u LOCALE)//线程锁,使get原子
const locale::facet*\u Psave=
_Faceptr::\u Psave;//指向惰性方面的静态指针
size\u t\u Id=\u Facet::Id;
const locale::facet*\u Pf=\u Loc.\u Getfacet(\u Id);
如果(_Pf!=0)
;//从区域设置中获取方面
否则如果(_Psave!=0)
_Pf=\u Psave;//已分配惰性方面
如果(_Facet::_Getcat(&_Psave,&_Loc)==(size_t)(-1))
#如果有例外情况
_抛出(错误的抛出,空的参数);//不允许懒惰
....
....
....
}
你能帮帮我吗

问候,,
Sumit

我在Windows7 64位上的VisualStudio2008应用程序中使用Boost 1.55的静态库构建时遇到了同样的问题,其中主可执行文件和两个DLL都链接到Boost。我不确定你的问题是否与我的问题相同,因为你没有提到使用DLL,但当我第一次开始调查这个问题时,我认为这与我无关

如果您只是对解决此问题的最直接的方法感兴趣,那么将Boost构建为共享库就可以了。具体来说,我的意思是将b2命令行的
链接
属性设置为
共享
,而不是
静态

解释 使用静态库生成出现问题的原因是Boost.Locale使用对象来执行文本转换操作,如大写和规格化
std::locale::facet
类需要有一个
id
静态成员变量,该变量在静态初始化期间构造时,其唯一值由标准库实现分配

使用静态库时的问题是,所有可执行文件和DLL都从静态库中获取自己的静态成员变量的不同副本,如中所述。使用
boost::locale::generator::operator()
生成区域设置时,它只会将
std::locale::facet
对象安装到具有
id
成员变量的区域设置中,该变量是包含该调用的同一DLL或可执行文件的一部分

正如我上面所说的,解决这个问题最直接的方法是将Boost构建为一个共享库。这样,Boost.Locale的静态成员变量将只有一个副本。具体来说,它们将位于Boost.Locale DLL中

替代解决方案 通过使用Boost.locale确保所有DLL和可执行文件中的所有
std::locale::facet
对象都安装到您尝试使用的
std::locale
对象中,可以使用Boost的静态库构建实现这一点

您可以使用下面的一些代码来实现这一点。对于DLL,当其第二个参数
fdreason
DLL\u PROCESS\u ATTACH
时,您可以在
DllMain
中调用它,对于可执行文件,您可以在
WinMain
或其他一些应用程序入口点(如果您使用的是MFC或Qt)中调用它

代码的重要部分是,它在每次运行时都使用全局区域设置作为基本区域设置,并将新生成的区域设置安装为新的全局区域设置。这与
boost::locale::generator::operator()
所做的不同,因为它使用
std::locale::classic
作为基本区域设置,并且不能修改。通过从每个DLL和可执行文件调用它,您将把它们的每个
std::locale::facet
对象安装到全局语言环境中

void setup_global_locale()
{
    const boost::locale::generator generator;
    const std::locale locale = generator.generate( std::locale(), "" );
    std::locale::global( locale );
}