Почему для pthread_mutexattr_settype() требуется макрос _GNU_SOURCE, хотя он соответствует стандарту POSIX/IEEE?

Я написал многопоточную серверную программу на языке C, которая возвращает все данные, отправляемые клиентом.

Первоначально я использовал функцию poll() в своей программе для обнаружения события POLLRDHUP, для этого я определил макрос _GNU_SOURCE (это событие определено здесь).

Позже я обновил свой код и удалил функцию poll(), однако забыл удалить макрос _GNU_SOURCE.

Теперь мой код, наконец, завершен (и немного длинный для публикации, более 250 строк). Перед удалением макроса я компилировал свою программу, используя:

gcc multi_thread_socket_v4.c -Wall -Werror -g -lpthread -o multi_thread_socket

и он работал нормально: ни ошибок, ни предупреждений

После того, как я удалил определение макроса и скомпилировал его с помощью той же командной строки, вывод gcc был таким:

multi_thread_socket_v4.c: In function ‘main’:
multi_thread_socket_v4.c:194: warning: implicit declaration of function ‘pthread_mutexattr_settype’
multi_thread_socket_v4.c:194: error: ‘PTHREAD_MUTEX_ERRORCHECK’ undeclared (first use in this function)
multi_thread_socket_v4.c:194: error: (Each undeclared identifier is reported only once
multi_thread_socket_v4.c:194: error: for each function it appears in.)

Я включил все необходимые библиотеки, так как изначально все работало нормально.

Я заглянул в pthread.h на /usr/include/pthread.h и узнал следующее:

/* Mutex types.  */
enum
{
  PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
  ,
  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
  /* For compatibility.  */
  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};

и это:

#ifdef __USE_UNIX98
/* Return in *KIND the mutex kind attribute in *ATTR.  */
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
                      __attr, int *__restrict __kind)
     __THROW __nonnull ((1, 2));

/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
   PTHREAD_MUTEX_DEFAULT).  */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
     __THROW __nonnull ((1));

Я проверил здесь, чтобы проверить, является ли __USE_UNIX98 макросом тестирования функций, но его там не было. .

Поэтому, пожалуйста, помогите мне понять причины ошибки, потому что функция и макрос, где gcc, показывают ошибку определены в стандарте POSIX. Я не знаю, какая дополнительная информация о моей проблеме потребуется, поэтому, пожалуйста, скажите мне, я обновлю свой вопрос.


person Don't You Worry Child    schedule 22.08.2013    source источник
comment
Самый очевидный ответ — эта функция не в Posix, а только в Linux. По умолчанию библиотека pthread пытается соответствовать Posix.   -  person Kerrek SB    schedule 22.08.2013
comment
Также обратите внимание, что макросы с двойным подчеркиванием не предназначены для использования вами; они сбрасываются внутри. Вы можете использовать только макросы верхнего уровня, такие как _GNU_SOURCE и _BSD_SOURCE, чтобы управлять тем, какие части библиотеки извлекаются.   -  person Kerrek SB    schedule 22.08.2013
comment
@KerrekSB: но функция pthread_setattr_settype() и макрос PTHREAD_MUTEX_ERRORCHECK являются стандартом POSIX , так зачем им нужно, чтобы _GNU_SOURCE было определено?   -  person Don't You Worry Child    schedule 22.08.2013
comment
Но они не являются стандартными C, поэтому им нужно что-то быть определено... не обязательно _GNU_SOURCE, который представляет собой кухонную раковину, которая втягивает множество вещей.   -  person Jim Balter    schedule 22.08.2013


Ответы (3)


Вы должны использовать

#define _POSIX_C_SOURCE 200112L

если вы хотите использовать функции POSIX, такие как pthread_mutexattr_settype... см. http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html

Другая возможность

#define _XOPEN_SOURCE 700

См. http://man7.org/linux/man-pages/man7/feature_test_macros.7.html и http://pubs.opengroup.org/onlinepubs/9699919799/

Параметр _GNU_SOURCE включает POSIX и множество других определений.

P.S. Я ожидаю, что включение <pthread.h> включает <features.h>, который по умолчанию определяет _POSIX_C_SOURCE как 200112L, но возможно, что вы определили что-то, что переопределяет это... см. /usr/include/features.h в вашей системе для получения подробной информации о символах и их Применение.

person Jim Balter    schedule 22.08.2013
comment
Понял, буду читать. Между прочим, эта ссылка, которую я нашел, является более поздней стандартной версией. - person Don't You Worry Child; 22.08.2013
comment
@nishant Эта ссылка находится внутри той, которую я дал. Я действительно не думаю, что вам нужно их читать, вам просто нужно предоставить определения. Что я здесь делаю, так это отвечаю на ваш вопрос. - person Jim Balter; 22.08.2013
comment
Спасибо, хотя _XOPEN_SOURCE 700 справился с задачей (как и _GNU_SOURCE). но не повлияет ли это на другие функции? Я имею в виду, что другие функции могут начать вести себя по-другому. - person Don't You Worry Child; 22.08.2013
comment
@nishant В основном это влияет на то, какие символы видны, а не на поведение. Вы могли бы получить изменения в поведении, если бы явно запрашивали старые устаревшие версии стандартов. - person Jim Balter; 22.08.2013

Это не так, ваша проблема, вероятно, заключается в другом.

Я только что скомпилировал тривиальную программу со следующим содержанием:

#include <pthread.h>

int main(int argc, char **argv)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

    return 0;
}

Это прекрасно компилируется с gcc -pthread -Wall -Werror a.c.

Возможно, это вызвано другой частью вашей программы, например. сделать что-нибудь глупое, например, определить _PTHREAD_H, или какой-нибудь другой мелкий саботаж.

Вы можете попытаться получить минимальный тестовый пример, используя такой инструмент, как дельта или creduce, что, вероятно, сделает проблему очевидной.

person Hasturkun    schedule 22.08.2013
comment
Ваш код дает ту же ошибку на моей машине. Технические характеристики машины: Операционная система: SLES 10 SP3 x86-64. - person Don't You Worry Child; 22.08.2013
comment
@nishant Здесь есть и другие ответы. Попробуйте мой. - person Jim Balter; 22.08.2013
comment
@nishant: Это довольно странно. Я построил это на ванильной установке Debian. Насколько я знаю, вам не нужно явно определять какие-либо макросы функций, поскольку features.h, включенный из pthread.h, должен определять их, если ничего другого не определено (именно поэтому это компилируется здесь, что я только что проверил с помощью gcc -E -fdirectives-only.) - person Hasturkun; 22.08.2013
comment
Я также отмечу, что установка некоторых вещей нарушит это, например. определение __STRICT_ANSI__ (посредством флага -ansi), или _POSIX_SOURCE, или _POSIX_C_SOURCE. (в моем случае это заканчивается установкой __USE_XOPEN2K8, которая включает функцию) - person Hasturkun; 22.08.2013
comment
Я изучил вывод gcc file.c -E -fdirectives-only но нигде не определялся __USE_UNIX98. Однако после #define _XOPEN_SOURCE 700 эта строка #define __USE_UNIX98 была в конце. - person Don't You Worry Child; 22.08.2013

Когда вы используете старые библиотеки (например, 2.1.x), вы должны использовать

#define __USE_UNIX98

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

person Emilio    schedule 22.03.2016