Защо е необходим макрос _GNU_SOURCE за pthread_mutexattr_settype(), докато е в стандарта 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 или някакъв друг незначителен саботаж.

Може да опитате да получите минимален тестов случай, като използвате инструмент като delta или 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 инсталация. AFAIK, не трябва да се налага изрично да дефинирате никакви макроси на функции, тъй като 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