使用LANG = en_US.UTF-8在MacOS 10.6上执行std :: locale breakage

时间:2009-11-16 21:42:46

标签: c++ cocoa macos boost

我有一个C ++应用程序,我正在移植到MacOSX(特别是10.6)。该应用程序大量使用C ++标准库和提升。我最近在应用程序中发现了一些我很难理解的破损。

基本上,boost文件系统库在程序运行时会抛出运行时异常。通过一些调试和谷歌搜索,我将违规调用减少到以下最小程序:

#include <locale>

int main ( int argc, char *argv [] ) {
    std::locale::global(std::locale(""));
    return 0;
}

当我通过g ++运行并在设置了LANG=en_US.UTF-8的环境中执行生成的程序时,该程序失败(当我创建一个新的控制台窗口时,我的计算机上的程序是默认bash会话的一部分)。清除环境变量(setenv LANG=)允许程序无问题地运行。但我很惊讶我在默认配置中看到了这种破坏。

我的问题是:

  1. MacOS 10.6上此代码的预期行为是什么?
  2. 适当的解决方法是什么?我无法真正重写该函数,因为我们使用的boost库的版本在内部执行此语句作为文件系统库的一部分。
  3. 为了完整起见,我应该指出,通过'open'命令(或从Finder)启动时,合成此代码的程序会崩溃,但是当Xcode在调试模式下运行程序时则不会崩溃。

    编辑上述代码在10.6.1上给出的​​错误是:

    $ ./locale 
    terminate called after throwing an instance of 'std::runtime_error'
      what():  locale::facet::_S_create_c_locale name not valid
    Abort trap
    

5 个答案:

答案 0 :(得分:9)

好的我没有给你答案,但我有一些线索:

  • 这不仅限于OS X 10.6。我在10.4机器上得到了相同的结果。
  • 我查看了GCC source for libstdc++,并在_S_create_c_locale周围寻找。我发现的是config/locale/generic/c_locale.cc的第143行。那里的评论说:“目前,通用模型只支持”C“语言环境。”这没有前途。事实上,如果我LANG=C运行时错误消失了,但{em>任何 LANG的其他值,我尝试会导致相同的错误,无论我给{{{{ 1}}构造函数。 (我尝试了locale,“C”,“”和默认值。这可以追溯到GCC 4.0
  • 同一页面上有关于此主题的libstdc++ mailing list discussion的引用。我不知道它有多么富有成效:我只是稍微关注它,而且技术非常快。

这些都没有告诉您为什么10.6上的默认语言环境不适用于locale::classic(),但它确实提出了一种解决方法,即在运行程序之前设置std::locale

答案 1 :(得分:6)

我最近在Ubuntu 14.04 LTS和运行最新Raspbian Wheezy的Raspberry Pi上遇到过这个问题。

它与OS X无关,而是与G ++和Boost(至少高达V1.55)的组合以及某些平台上的默认语言环境设置。有一些与此问题相关的Boost bug票证,请参阅 ticket #4688ticket #5928

我的解决方案&#34;是this AskUbuntu posting建议的第一个做一些额外的语言环境设置:

sudo locale-gen en_US en_US.UTF-8
sudo dpkg-reconfigure locales

但是,我还必须确保将环境变量LC_ALL设置为LANG的值(建议将其放在.profile中):

export LC_ALL=$LANG

在我的情况下,我使用区域设置en_US.UTF-8

最后的评论:OP说&#34;当我通过g ++&#34;运行时,这个程序失败了。我知道这个线程是在2009年开始的,但今天绝对没有必要在Mac上使用GCC或G ++ ,免费提供更好的LLVM / Clang编译器套件,请参阅XCode home page

答案 2 :(得分:4)

情况仍然相同。 可以通过

获得一些功能
setlocale( LC_ALL, "" );

对于我的两个数据点,这可以在宽iostream上获得UTF-8编码,但不能使用货币格式。

locale::global( locale( "" ) );

应该是等效的,但如果随后在同一个程序中运行则会崩溃。

答案 3 :(得分:3)

我遇到了同样的问题,检查了LANG和LC_MESSAGES,当你通过Finder午餐时,它们没有设置,所以以下几行保存了这一天:

unset("LANG");
unset("LC_MESSAGES");

答案 4 :(得分:1)

_S_create_c_locale异常似乎表明存在某种错误配置:检查LC_ALLLANG环境变量的设置是否存在于locale -a的输出中。

$ env LC_ALL=xx_YY ./test
terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid
Aborted
$ env LC_ALL=C ./test
$ echo $?
0

但是由于你使用的是OS X,我不确定应该如何处理语言环境信息。