Подтвердить что ты не робот

Std:: locale breakage на MacOS 10.6 с LANG = en_US.UTF-8

У меня есть приложение на С++, которое я переношу на MacOSX (в частности, 10.6). Приложение сильно использует стандартную библиотеку С++ и повышает. Недавно я заметил некоторый порыв в приложении, с которым мне трудно понять.

В принципе, библиотека файловой системы boost генерирует исключение во время выполнения при запуске программы. С небольшим количеством отладки и поиска в Google, я уменьшил оскорбительный вызов до следующей минимальной программы:

#include <locale>

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

Эта программа не работает, когда я запускаю ее через g++ и выполняю результирующую программу в среде, где установлен LANG=en_US.UTF-8 (который на моем компьютере является частью сеанса bash по умолчанию при создании нового окна консоли). Очистка переменной окружения (setenv LANG=) позволяет программе работать без проблем. Но я удивлен, что вижу эту поломку в конфигурации по умолчанию.

Мои вопросы:

  • Является ли это ожидаемым поведением для этого кода в MacOS 10.6?
  • Каким будет подходящее обходное решение? Я не могу переписать функцию раньше, потому что используемая нами версия библиотек boost выполняет это внутреннее выражение как часть библиотеки файловой системы.

Для полноты я должен указать, что программа, из которой был синтезирован этот код, сбрасывается при запуске через команду "open" (или из Finder), но не тогда, когда Xcode запускает программу в режиме Debug.

edit Ошибка, указанная в приведенном выше коде 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
4b9b3361

Ответ 1

Я столкнулся с этой проблемой совсем недавно на Ubuntu 14.04 LTS и на малине Pi, в которой работает последний Raspbian Wheezy.

Это не имеет ничего общего с OS X, скорее, с комбинацией g++ и Boost (по крайней мере, до V1.55) и стандартными языковыми настройками на определенных платформах. Существуют биг-коды Boost, связанные с этой проблемой, см. билет # 4688 и билет # 5928.

Мое "решение" было первым, чтобы выполнить некоторую дополнительную настройку локали, как было предложено этой публикацией AskUbuntu:

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

Но тогда я также должен был убедиться, что переменная окружения LC_ALL установлена ​​в значение LANG (желательно поместить это в ваш .profile):

export LC_ALL=$LANG

В моем случае я использую locale en_US.UTF-8.

Заключительное замечание: OP сказал: "Эта программа не работает, когда я запускаю ее через g++". Я понимаю, что этот поток был запущен в 2009 году, но сегодня абсолютно нет необходимости использовать GCC или g++ на Mac, гораздо лучший набор компиляторов LLVM/Clang доступен бесплатно Apple, см. Домашняя страница XCode.

Ответ 2

Хорошо, у меня нет ответа для вас, но у меня есть некоторые подсказки:

  • Это не ограничивается OS X 10.6. Я получаю тот же результат на машине 10.4.
  • Я посмотрел на источник config/locale/generic/c_locale.cc. В комментарии там говорится:" В настоящее время общая модель поддерживает только локаль "C". Это не обещает. На самом деле, если я выполняю LANG=C, ошибка времени выполнения исчезает, но любое другое значение для LANG Я пытаюсь вызвать ту же ошибку, независимо от того, какие аргументы я передаю конструктору locale. (Я пробовал locale::classic(), "C", "и по умолчанию). Это верно еще в GCC 4.0
  • На этой же странице есть ссылка на обсуждение списка рассылки libstdС++ на эту тему. Я не знаю, насколько это плодотворно: я только немного пошел вниз, и он очень техничен очень быстро.

Ничто из этого не говорит о том, почему локаль по умолчанию на 10.6 не будет работать с std::locale, но он предлагает обходное решение, которое должно установить LANG=C перед запуском программы.

Ответ 3

У меня была та же проблема, я проверял LANG и LC_MESSAGES, и они не установлены, когда вы обедаете приложение через Finder, поэтому следующие строки сохранили день:

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

Ответ 4

Ситуация остается прежней. Но некоторые функции могут быть достигнуты

setlocale( LC_ALL, "" );

Это дает вам кодировку UTF-8 в широком iostream, но не форматирование денег, для моих двух точек данных.

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

должен быть эквивалентным, но он сработает, если впоследствии будет запущен в той же самой программе.

Ответ 5

Исключение _S_create_c_locale, по-видимому, указывает на некорректную конфигурацию: проверьте, что независимо от вашей переменной LC_ALL или LANG, существует на выходе 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, я не совсем уверен, как должна обрабатываться информация о локали.