Почему std :: locale (""). Name () дает разные результаты для clang и gcc? - PullRequest
5 голосов
/ 05 октября 2019

Компиляция и запуск следующего кода на моем компьютере (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 голосов
/ 15 октября 2019

Вы правы "Набор допустимых значений строковых аргументов -" C "," "и любые значения, определенные реализацией ..." Но если вы попытаетесь установить неизвестный локальныйможет быть возвращен локальным ("")), он выдаст ошибку во время выполнения.

Взгляните на исходный код функции 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 ++). Вы можете легко найти его в нескольких местах: отчет об ошибке 1 , отчет об ошибке 2 , пример 1 . Как вы можете видеть в настоящее время libstdc ++ поддерживает только локали "C".

Я говорю, используйте ICU:)

0 голосов
/ 14 октября 2019

Различия, вероятно, связаны с тем, что clang ++ использует libc++, тогда как g ++ использует libstdc++. Функция std::locale() определена в любом из них, и реализации различаются.

Вы можете проверить это с помощью strace (если доступно) следующим образом:

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

В этомНапример, используется libstdc++.

...