netdb.h неправильно связывается - PullRequest
12 голосов
/ 27 сентября 2011

Я пытаюсь скомпилировать эту программу, как указано в Руководство Биджа по сетевому программированию на стр. 19.

#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>

int main() {
    int status;
    struct addrinfo hints;
    struct addrinfo *servinfo;          /* Will point to the results */
    memset(&hints, 0, sizeof hints);    /* Make sure the struct is empty */
    hints.ai_family = AF_UNSPEC;        /* Don't care IPv4 or IPv6 */
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(1);
    }

    /* Servinfo now points to a linked list of 1 or more struct addrinfos
        ... do everything until you don't need servinfo anymore .... */

    freeaddrinfo(servinfo); /* Free the linked-list */

    return 0;
}    

Среди других ошибок я вижу

../main.c:8:18: error: storage size of ‘hints’ isn’t known
../main.c:13:19: error: ‘AI_PASSIVE’ undeclared (first use in this function)
../main.c:16:3: warning: implicit declaration of function ‘gai_strerror’

Похоже, что gcc не связывается с netdb.h.Eclipse, интегрированная среда разработки, которую я использую для сборки, без проблем находит файл.Вот команда компилятора:

gcc -O0 -g3 -pedantic -Wall -c -fmessage-length=0 -ansi -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.c"

Добавление -lnetdb не решает проблему.Также ...

~> find /usr/include/ -name netdb.h
/usr/include/bits/netdb.h
/usr/include/gssrpc/netdb.h
/usr/include/netdb.h
/usr/include/rpc/netdb.h

Я думаю, что эти файлы были предустановлены на моем хосте openSUSE.Почему gcc не обнаруживает netdb.h?Или я делаю неправильный вывод?

Ответы [ 4 ]

17 голосов
/ 27 сентября 2011
../main.c:8:18: error: storage size of ‘hints’ isn’t known
../main.c:13:19: error: ‘AI_PASSIVE’ undeclared (first use in this function)
../main.c:16:3: warning: implicit declaration of function ‘gai_strerror’

Похоже, что gcc не связывается с netdb.h ....

Это не ссылки ошибок, и вам не нужен общий объект netdb файл (такого зверя нет; netdb.h просто определяет структуры данных и макросы для использования в вашем коде).

Это ошибки компилятора: gcc жалуется, потому что вы используете имена что он не распознает (AI_PASSIVE) и типы данных, для которых структура неизвестна (struct addrinfo).

Код, который вы представили, кажется правильным, и addrinfo определяется в /usr/include/netdb.h. Что произойдет, если вы скомпилируете это как это:

gcc -c main.c

У вас все еще такое же поведение? Если это так, взгляните на вывод из:

gcc -E main.c

Это генерирует предварительно обработанную версию кода со всеми #include заявления заменены их фактическим содержанием. Вы должны быть в состоянии пройти через это и посмотреть, действительно ли компилятор получает /usr/include/netdb.h если находит что-то еще:

$ gcc -E foo.c | grep netdb.h | awk '{print $3}' | sort -u

Что в моей системе дает:

"/usr/include/bits/netdb.h"
"/usr/include/netdb.h"
"/usr/include/rpc/netdb.h"

Когда вы добавляете -ansi в командную строку, вы меняете способ gcc ведет себя так, что сломает ядро ​​Linux и многие системы заголовочные файлы. Определение addrinfo в netdb.h защищено как это:

#ifdef  __USE_POSIX
/* Structure to contain information about address of a service provider.  */
struct addrinfo
{
  int ai_flags;                 /* Input flags.  */
  int ai_family;                /* Protocol family for socket.  */
  int ai_socktype;              /* Socket type.  */
  int ai_protocol;              /* Protocol for socket.  */
  socklen_t ai_addrlen;         /* Length of socket address.  */
  struct sockaddr *ai_addr;     /* Socket address for socket.  */
  char *ai_canonname;           /* Canonical name for service location.  */
  struct addrinfo *ai_next;     /* Pointer to next in list.  */
};

// ...other stuff...
#endif

Когда вы запускаете gcc с флагом -ansi, это отменяет __USE_POSIX макрос, потому что вещи, защищенные этим, могут не быть строго соответствует ANSI. Вы можете увидеть разницу, если вы сравните это:

gcc -E /usr/include/netdb.h

С этим:

gcc -E -ansi /usr/include/netdb.h

Только первая содержит структуру addrinfo.

3 голосов
/ 06 мая 2013

добавить в начало вашего файла

#define _XOPEN_SOURCE 600
0 голосов
/ 13 февраля 2014

Используйте #include <netinet/in.h> .... вместе с этим ..... и в компиляции (ubuntu) ....

gcc server/client -o server/client.c -lpthread

(здесь lpthread - поток обработки линки).... которая решает твою проблему: -D

0 голосов
/ 27 сентября 2011

Связывание не прикрепляет файл заголовка к программе, предварительная обработка обрабатывает файлы заголовка.

Связывание присоединяет библиотеки общих объектов (смотрите / usr / lib) к скомпилированным объектам. Иногда недостаточно просто добавить «-lnetdb», поскольку библиотека может не находиться в пути компоновщика. В этом случае вам нужно использовать -L (путь) для добавления записи пути, чтобы директива -lnetdb могла найти правильный файл netdb.so.

...