Как получить POSIX strerror_r вместо версии GNU? - PullRequest
9 голосов
/ 16 июня 2010

Как мне получить 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.

Ответы [ 3 ]

7 голосов
/ 16 июня 2010

Из заголовка 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, но это не всегда относится к очень сжатым man-страницам.

Edit

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

#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), вы, вероятно, хотите позволить это сделать.Вы можете использовать --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().

3 голосов
/ 28 августа 2013

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

#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
2 голосов
/ 18 ноября 2010

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

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

...