netdb.h没有正确链接

Pie*_*ter 12 c networking linker

我正在尝试编译这个程序,如第19页的Beej网络编程指南中所述.

#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;
}    
Run Code Online (Sandbox Code Playgroud)

在其他错误中,我看到了

../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’
Run Code Online (Sandbox Code Playgroud)

似乎gcc没有链接netdb.h.Eclipse,我用来构建它的IDE,可以轻松找到该文件.这是编译器命令:

gcc -O0 -g3 -pedantic -Wall -c -fmessage-length=0 -ansi -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.c"
Run Code Online (Sandbox Code Playgroud)

添加-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
Run Code Online (Sandbox Code Playgroud)

我认为我的openSUSE主机上预装了这些文件.为什么不用gcc检测netdb.h?或者我得出了错误的结论?

lar*_*sks 17

../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’
Run Code Online (Sandbox Code Playgroud)

看来gcc没有与netdb.h链接....

这些不是链接错误,并且您不需要netdb共享对象文件(没有这样的野兽; netdb.h只需定义在您的代码中使用的数据结构和宏).

这些是编译器错误:gcc抱怨,因为你使用的是它无法识别的名称(AI_PASSIVE)和结构未知的数据类型(struct addrinfo).

您提供的代码似乎是正确的,并addrinfo 在其中定义/usr/include/netdb.h.如果你这样编译它会发生什么:

gcc -c main.c
Run Code Online (Sandbox Code Playgroud)

你还有同样的行为吗?如果是这样,看一下输出:

gcc -E main.c
Run Code Online (Sandbox Code Playgroud)

这将生成代码的预处理版本,并将所有 #include语句替换为其实际内容.你应该能够通过这个来看看编译器是否真正得到 /usr/include/netdb.h它,如果它找到了别的东西:

$ gcc -E foo.c | grep netdb.h | awk '{print $3}' | sort -u
Run Code Online (Sandbox Code Playgroud)

在我的系统上产生:

"/usr/include/bits/netdb.h"
"/usr/include/netdb.h"
"/usr/include/rpc/netdb.h"
Run Code Online (Sandbox Code Playgroud)

当您添加-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
Run Code Online (Sandbox Code Playgroud)

当您gcc使用该-ansi标志运行时,这将__USE_POSIX取消定义 宏,因为受此保护的内容可能不严格符合ANSI标准.如果你比较一下,你可以看到差异:

gcc -E /usr/include/netdb.h
Run Code Online (Sandbox Code Playgroud)

有了这个:

gcc -E -ansi /usr/include/netdb.h
Run Code Online (Sandbox Code Playgroud)

只有前者包含addrinfo结构.