Как получить POSIX strerror_r вместо версии GNU?

Как получить POSIX strerror_r вместо версии GNU?

Я компилирую с помощью g++ на Ubuntu 8.04 с glibc версии 2.7 (на основе того, что есть в ).

Изменить

На приведенной выше странице руководства говорится:

Требования к макросам тестирования функций для glibc (см. feature_test_macros(7)):

   The XSI-compliant version of strerror_r() is provided if:
   (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
   Otherwise, the GNU-specific version is provided.

Затем он говорит в feature_test_macros(7):

   If no feature test macros are explicitly defined, then the following feature
   test macros are defined by default: _BSD_SOURCE, _SVID_SOURCE, _POSIX_SOURCE,
   and _POSIX_C_SOURCE=200809L (200112L in glibc versions before 2.10; 199506L in
   glibc versions before 2.4; 199309L in glibc versions before 2.1).

Так что я должен получить версию POSIX, но вместо этого я получаю версию GNU.


person Robert S. Barnes    schedule 16.06.2010    source источник
comment
Вы уверены, что ни один из ваших файлов заголовков или заголовков 3. party не определяет, например. _GNU_SOURCE ?   -  person nos    schedule 16.06.2010


Ответы (3)


Из заголовка string.h:

/* Reentrant version of `strerror'.
   There are 2 flavors of `strerror_r', GNU which returns the string
   and may or may not use the supplied temporary buffer and POSIX one
   which fills the string into the buffer.
   To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L
   without -D_GNU_SOURCE is needed, otherwise the GNU version is
   preferred.  */

Обратите внимание: будьте осторожны при использовании расширений GNU, включайте их (_GNU_SOURCE) последними, перед включением заголовков, на которые вы хотите повлиять (или отмените их определение стратегически). Однако не стоит беспокоиться, если вы не используете расширения GNU.

Как правило, если GNU отклоняется от POSIX в поведении по умолчанию, вы увидите в заголовке некоторые комментарии, указывающие, как вы можете получить поведение POSIX. Это также (обычно) задокументировано в руководстве glibc, но это не всегда приводит к очень сжатым справочным страницам.

Изменить

Попробуйте этот простой тест:

#include <string.h>
#ifdef _GNU_SOURCE
#error "Something turned it on!"
#endif

Или более прямо

#ifdef _GNU_SOURCE
#undef _GNU_SOURCE
#endif
#include <string.h>

Если определено _POSIX_C_SOURCE={version}, вы должны иметь версию POSIX, если что-то еще не привело к тому, что версия GNU была предпочтительнее.

Единственное, что я могу придумать, это _GNU_SOURCE. Я уверен, что этого нет в ваших флагах командной строки, вы бы это видели. Возможно, его включила другая включенная библиотека.

Это то, что я имел в виду, говоря о «сложности» расширений, когда запрашивал предпочтение реализации POSIX, даже если вы не тот, кто их включает.

Изменить

Если что-то включается _GNU_SOURCE (я не могу вспомнить, работает ли boost или нет, я не использую C++ почти так же часто, как C), вы, вероятно, захотите разрешить это. Вы можете использовать --undef "[macro]" -U[macro] из командной строки. Однако это не сработает, если код библиотеки выглядит так:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <string.h>

#ifdef _GNU_SOURCE
#error "It didn't work"
#endif

int main(void)
{
   return 0;
}

Проблема в том, что к тому времени, когда ваш код действительно включает string.h, что-то еще уже включило расширения и включило его. Включение охранников естественно не позволит вам включить его дважды.

Попробуйте явным образом отключить _GNU_SOURCE и включить string.h до всего. Это предотвращает включение этих расширений другими библиотеками. Однако эти библиотеки могут не работать без них. Некоторый код просто «ожидает» поведения GNU и не включает откат к POSIX.

Я испытал подобное разочарование из-за того, что код библиотеки не работает без asprintf().

person Tim Post♦    schedule 16.06.2010
comment
Чего я не понимаю, так это того, что в документации сказано, что _POSIX_C_SOURCE=200112L определено по умолчанию (см. редактирование моего OP), поэтому я не понимаю, почему я получаю версию GNU. - person Robert S. Barnes; 16.06.2010
comment
Я попробовал первый, и, видимо, что-то его включает. Ничто в моем коде не включает его, поэтому я предполагаю, что это должно быть что-то из glibc, stdlib++ ( STL ) или Boost. Есть ли способ отменить его глобально из командной строки? - person Robert S. Barnes; 17.06.2010
comment
@Robert - я не верю, что glibc / stdlib++ включает расширения по умолчанию. Вероятно, это происходит из boost или другой библиотеки. Если ваш заголовок строки включается первым (до повышения), с -D_POSIX_C_SOURCE он должен быть выключен. Смотрите мою правку. - person Tim Post♦; 17.06.2010
comment
+1 Итак, я думаю, мне нужно попробовать включить <cstring> перед любым из заголовков Boost и посмотреть, поможет ли это и не нарушит ли процесс Boost. - person Robert S. Barnes; 17.06.2010
comment
Я провел тест, в котором я проверил _GNU_SOURCE как самый первый оператор в файле, и, по-видимому, он определен по умолчанию g++. Вопрос в том, отключится ли он из командной строки... - person Robert S. Barnes; 21.06.2010
comment
@Robert - В ускорении? Я сомневаюсь в этом. Другие вещи, которые не так хорошо протестированы (или написаны), которые не отступают, если общие расширения не включены ... трудно сказать. «Лучшим» вариантом может быть реализация вашей собственной реентерабельной версии strerror(), что не так сложно. Опять же, если ничего не сломается.. не надо чинить :) - person Tim Post♦; 21.06.2010
comment
@Tim Post - Нет, не Boost, g++. Я помещаю тест в качестве первого оператора в файл перед любыми #include. Кажется, что g++ определяет это. - person Robert S. Barnes; 21.06.2010
comment
@Robert - я имею в виду, что его неопределенность, вероятно, не сломает ускорение. - person Tim Post♦; 21.06.2010
comment
@RobertS.Branes Преобразование ломает для меня libstdc++. - person user877329; 28.08.2013
comment
g++ undeed по умолчанию включает _GNU_SOURCE, а его отключение вручную ломает libstdc++. По-видимому, libstdc++ полагается на определенные определения в других заголовках, которые появляются только тогда, когда определено _GNU_SOURCE. - person spectras; 07.04.2017

Это обходной путь для конкретной реализации.

#ifdef __cplusplus
extern "C"
    {
#endif
    extern 
    int __xpg_strerror_r(int errcode,char* buffer,size_t length);
    #define strerror_r __xpg_strerror_r

#ifdef __cplusplus
    }
#endif
person user877329    schedule 28.08.2013
comment
зачем указывать свою версию ядра, когда мы говорим о пользовательском пространстве? - person Janus Troelsen; 18.03.2015

Хотя по стандарту не требуется быть потокобезопасным, я не могу себе представить, как здравомыслящий человек может написать не потокобезопасный strerror. Что люди делают, gunzip строки ошибок во время выполнения или что-то в этом роде?! Хороший strerror должен возвращать указатель либо на строковые константы в стандартной библиотеке, либо на константную mmap память из файла сообщений локали.

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

person R.. GitHub STOP HELPING ICE    schedule 17.11.2010
comment
Ты забавный. Это второе предложение заставило меня LOL'ing. Ничего себе, я не могу поверить, что я только что напечатал LOL'ing, черт возьми, это снова. Можно подумать, что мне 13, когда я печатаю подобные вещи. Бах, наверное, это просто слишком много пива и слишком много модульных тестов за одну ночь. - person Robert S. Barnes; 18.11.2010
comment
Еще одна подобная функция с нелепым вариантом _r — это readdir. Существует совершенно хорошая структура DIR для хранения буфера (или указатель на динамически выделяемый буфер для каждого потока, если люди действительно настаивают на чтении одного DIR из нескольких потоков) и абсолютно нет оправдания для добавления readdir_r (с неуклюжим интерфейсом) . - person R.. GitHub STOP HELPING ICE; 18.11.2010
comment
На справочной странице даже перечислены примеры: неизвестная ошибка NNN. И это без перевода. - person o11c; 08.05.2017
comment
FWIW стандарт был обновлен, чтобы потребовать, чтобы readdir был потокобезопасным. Надеюсь, strerror будет следующим. - person R.. GitHub STOP HELPING ICE; 30.04.2018
comment
@ o11c: Действительно, сгенерированные сообщения для недопустимых номеров ошибок являются очевидным случаем, когда будет возвращена неизменяемая строка. Компромисс, который я предлагаю для стандартизации, требует, чтобы strerror был потокобезопасным только тогда, когда переданный ему номер ошибки действителен. - person R.. GitHub STOP HELPING ICE; 30.04.2018