【问题标题】:Setting locales on OS X crashes在 OS X 上设置语言环境崩溃
【发布时间】:2012-06-26 18:02:55
【问题描述】:

以下代码在 Linux 上运行良好,但在 OS X 10.7 上引发异常:

#include <iostream>
#include <locale>
#include <stdexcept>

int main() try {
    std::locale::global(std::locale(""));
    std::cout << "Using locale: " << std::locale().name() << "\n";
}
catch (std::runtime_error const& e) {
    std::cout << e.what() << "\n";
    return 1;
}

OS X 上的输出是:

locale::facet::_S_create_c_locale 名称无效

但是,标准明确指出

有效的字符串参数值集是"C""",以及任何实现定义的值。

所以任何导致上述行为的原因都违反了标准。

使用的编译器是clang++ 3.1 (tags/Apple/clang-318.0.58);我也尝试使用通过 Homebrew 安装的 GCC 4.7,结果相同。

其他人可以验证这个问题吗?是什么原因造成的?我做错什么了吗?这是 OS X 中的错误吗?

(也许这个relates to another xlocale problem 但错误实际上完全不同。)

【问题讨论】:

  • 我认为这(几乎)是this question的副本...
  • @EitanT 很好的发现,它是(exact 重复)!谢谢。
  • 我认为您没有使用 xlocale。我相信您的问题在于 libstdc++,它使用不同的语言环境支持库(OS X 显然不支持该库,因为问题 EitanT 链接到状态)。我认为如果您切换到 libc++,您的程序将可以工作。尽管作为我的问题的详细信息,由于 xlocale 中的错误,libc++ 中的某些语言环境存在问题。
  • @bames53 太棒了,介意在答案中写这个吗?然后我可以投票并接受。没错,这有其自身的问题(打印时的语言环境名称为空),但至少在某些输入上实际使用时,它现在似乎使用的是 UTF-8。

标签: c++ macos locale xlocale


【解决方案1】:

我认为您没有使用 xlocale。我相信您的问题在于 libstdc++,它使用了 OS X 不支持的不同语言环境支持库,因为问题 EitanT 链接到状态。

如果你切换到 libc++,你的程序就可以工作了。

【讨论】:

    【解决方案2】:

    上面的海报是正确的……问题出在 libstdc++ 上。我想添加我的答案,因为如何让 OS X 链接到 libc++ 并不简单,我花了一个多小时才弄清楚。

    通过g++ -libstd=libc++clang++ -libstd=libc++ 或别名c++ -libstd=libc++ 调用编译器/链接器都将失败。

    从命令行编译简单程序而不是弄乱Xcode的额外开销的解决方案是允许Xcode使用命令xcrun clang++ -stdlib=libc++来处理链接

    xcrun 允许 Xcode 管理工具链,并将构建一个成功的可执行文件,cout.imbue(locale(foo)) 将成功工作。

    【讨论】:

    • 实际上,在执行以下操作时,您可以将 libc++ 与 clang++ 一起使用:export CXX="clang++-$cxxver -stdlib=libc++"export CXXFLAGS="-nostdinc++ -isystem /usr/local/lib/llvm-$cxxver/include/c++/v1"(对于适当的 $cxxver)。我不会在流程的任何部分都依赖 Xcode,尤其是在您通过 Homebrew 安装了较新版本的 Clang 之后。
    • 康拉德,感谢您的帮助,但您能帮助新手并解释一下这些命令的作用吗?
    • export 命令在终端中设置环境变量。 Familiarise yourself with the CXX and CXXFLAGS variables,它们对于 Unix 上的 C++ 开发很重要。现在,使用这些变量设置的选项是-nostdinc++,它禁止使用默认的标准库实现。 -libc++ 告诉 clang 使用 libc++ 而不是默认的 (libstdc++),-system … 告诉 clang 在哪里可以找到它。