我正在尝试编译这个程序,如 Beej 的网络编程指南第 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 是我用来构建它的 IDE,可以轻松找到该文件。这是编译器命令:
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 ?还是我得出了错误的结论?

最佳答案



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

这些是编译器错误:gcc 提示,因为您正在使用名称
它不识别( AI_PASSIVE )和数据类型
结构未知(struct addrinfo)。

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

gcc -c main.c

你仍然有同样的行为吗?如果是这样,请查看输出
的:
gcc -E main.c

这将生成代码的预处理版本,其中包含所有#include 语句替换为它们的实际内容。你应该
能够通过这个grep,看看编译器是否真的得到/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 结构。

关于c - netdb.h 未正确链接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7571870/

10-13 23:13