【问题标题】:std::locale breakage on MacOS 10.6 with LANG=en_US.UTF-8带有 LANG=en_US.UTF-8 的 MacOS 10.6 上的 std::locale 损坏
【发布时间】:2010-12-17 05:35:37
【问题描述】:

我有一个要移植到 MacOSX(特别是 10.6)的 C++ 应用程序。该应用程序大量使用 C++ 标准库和 boost。我最近发现应用中有一些我难以理解的问题。

基本上,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 库版本在内部执行此语句作为文件系统库的一部分。

为了完整起见,我应该指出,合成此代码的程序在通过“打开”命令(或从 Finder)启动时会崩溃,但在 Xcode 在调试模式下运行程序时不会崩溃。

edit以上代码在10.6.1上给出的​​错误是:

$ ./locale
在抛出 'std::runtime_error' 的实例后调用终止
  what(): locale::facet::_S_create_c_locale 名称无效
中止陷阱

【问题讨论】:

  • 您能否提供一段简短的代码来展示您看到的损坏情况,而不是无法显示它的通用示例? (这有时被称为测试用例。)它可能就像在您当前的示例中包含一个 boost.filesystem 调用一样简单。
  • 当您说“引发运行时异常”时,您到底看到了什么?
  • 他发布的代码确实存在问题,至少在我的机器上是这样。我会用我得到的输出来编辑他的问题。
  • 是的,我还注意到标准(如std::)C++ 语言环境支持在 Mac OS X 上似乎完全被破坏了。 std::locale("") 应该选择默认语言环境,但即使用户的环境设置为与 C 的 setlocale 一起使用的环境,也无法提供有效的语言环境。不值得回答,但值得评论。
  • 如我的回答中所述,这不仅仅是 10.6。在 10.4 上也是如此。

标签: c++ cocoa macos boost


【解决方案1】:

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

  • 这不仅限于 OS X 10.6。我在 10.4 机器上得到了相同的结果。
  • 我查看了GCC source for libstdc++ 并四处寻找_S_create_c_locale。我发现在config/locale/generic/c_locale.cc 的第 143 行。那里的评论说“目前,通用模型仅支持“C”语言环境。这并不乐观。事实上,如果我执行LANG=C,运行时错误就会消失,但我尝试LANG任何 其他值会导致相同的错误,无论我给locale 构造函数提供什么参数。 (我尝试了locale::classic()、“C”、“”和默认值)。早在GCC 4.0 就是如此
  • 同一页面在此主题上引用了libstdc++ mailing list discussion。我不知道它的成果如何:我只跟着它走了一小段路,它变得非常技术性非常快。

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

【讨论】:

  • 感谢您出色的刑警工作。如原始问题(设置LANG=)中所述,我已经使用了一种解决方法。我可以执行解决方法,但我仍然很好奇为什么默认配置似乎被破坏了。
  • 所以答案似乎是 libstdc++ 不支持 Mac OS X 上的“C”以外的语言环境。我尝试使用 libc++ 进行相同的测试,它确实有效。 (但是我注意到,虽然您可以构建使用非 UTF-8 编码的语言环境,但底层的 xlocal 支持不支持实际转换为此类语言环境或从此类语言环境转换。似乎只有 UTF-8 和可能的其他 Unicode 编码支持)。
【解决方案2】:

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

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

我的“解决方案”首先是按照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 说“当我通过 g++ 运行这个程序时,这个程序失败了”。我知道这个线程是在 2009 年开始的,但是今天完全不需要在 Mac 上使用 GCC 或 G++,更好的 LLVM/Clang 编译器套件可以从 Apple 免费获得,请参阅XCode home page

【讨论】:

    【解决方案3】:

    情况还是一样。但是一些功能可以通过

    获得
    setlocale( LC_ALL, "" );
    

    对于我的两个数据点,这可以让您在宽 iostreams 上进行 UTF-8 编码,但不是货币格式。

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

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

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,检查了 LANG 和 LC_MESSAGES,当您通过 Finder 午餐应用程序时它们没有设置,所以以下几行节省了一天:

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

      【讨论】:

        【解决方案5】:

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

        $ 环境 LC_ALL=xx_YY ./test 在抛出 'std::runtime_error' 的实例后调用终止 what(): locale::facet::_S_create_c_locale 名称无效 中止 $ 环境 LC_ALL=C ./test $回声$? 0

        但由于您使用的是 OS X,我不太确定应该如何处理区域信息。

        【讨论】:

        • locale -a 列出了您可能期望的语言环境 en_US.UTF-8,所以不幸的是,这还不够。
        猜你喜欢
        • 2021-11-20
        • 2010-12-01
        • 1970-01-01
        • 2018-10-23
        • 1970-01-01
        • 1970-01-01
        • 2017-09-15
        • 2021-06-12
        • 2022-01-24
        相关资源
        最近更新 更多