为什么std :: locale(“”)。name()在clang和gcc上给出不同的结果?

时间:2019-10-05 04:14:01

标签: c++ g++ locale clang++ setlocale

在我的计算机(MacOS 10.14.x)上编译并运行以下代码会导致在clang ++上打印空字符串,并在g ++上引发运行时错误。为什么?

#include <locale>
#include <iostream>


int main()
{
  std::cout << "User-preferred locale setting is " <<
    std::locale("").name().c_str() << '\n';

  return 0;
}
$ clang++ locale.cc
$ ./a.out 
User-preferred locale setting is 


$ g++-mp-8 locale.cc 
$ ./a.out 
terminate called after throwing an instance of 'std::runtime_error'
  what():  locale::facet::_S_create_c_locale name not valid
User-preferred locale setting is Abort trap: 6

$ clang++ --version
clang version 7.0.1 (tags/RELEASE_701/final)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-7.0/bin

$ g++-mp-8 --version
g++-mp-8 (MacPorts gcc8 8.3.0_0) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

目前,我认为这不是MacOS问题,因为在cppreference.com上运行示例也会产生不同的结果。

您可以在https://en.cppreference.com/w/cpp/locale/locale/name

上针对不同的编译器版本自己尝试。

在任何情况下,其报告都不会与以下内容相同:

#include <locale>
#include <iostream>
#include <string>

int main()
{
  std::cout << "User-preferred locale setting is "
            << setlocale(LC_ALL, "") << "\n";

  return 0;
}

两个编译器返回相同的结果(“ en_US.UTF-8”)。

我想念什么?

2 个答案:

答案 0 :(得分:0)

差异可能来自clang ++使用libc++而g ++使用libstdc++的事实。函数std::locale()是在上述两种方法中定义的,实现方式不同。

您可以使用strace(如果有)进行检查,如下所示:

$ strace -e file ./a.out
...
open("/usr/lib/.../libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
...

在此示例中,使用libstdc++

答案 1 :(得分:0)

您是对的“有效的字符串参数值的集合为” C“,”“,以及任何实现定义的值...” 但是,如果您尝试设置为未知的本地(可能由local(“”)返回),则会抛出运行时错误。

看看libstdc++-v3/config/locale/gnu/c_locale.cc的源代码

locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, __c_locale __old)
{
    __cloc = __newlocale(1 << LC_ALL, __s, __old);
    if (!__cloc)
    {
        // This named locale is not supported by the underlying OS.
        __throw_runtime_error(__N("locale::facet::_S_create_c_locale name not valid"));
    }
}

__newlocale函数是其中的一个。其C函数将处理传递给它的值的转换。

在MAC-OS上,看来libstdc++不能正确处理“”值,甚至在许多语言环境中都存在很多问题。

这是libstdc ++(由g ++使用)中的一个众所周知的问题。您可以在bug report 1bug report 2example 1的多个位置轻松找到它。如您所见,libstdc ++当前仅支持“ C”语言环境。

我说使用ICU :)