【问题标题】:netdb.h not linking properlynetdb.h 未正确链接
【发布时间】:2011-09-27 15:41:05
【问题描述】:

我正在尝试编译此程序,如第 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;
}    

在其他错误中,我看到了

../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?还是我得出了错误的结论?

【问题讨论】:

  • 我在 Linux Mint 20 上遇到了类似的问题。我的 IDE(VS 代码)无法识别 addrinfo 结构,并且在编译时出现以下错误:gethost.c: In function 'main ':gethost.c:52:5:警告:函数'freehostent'的隐式声明;你是说 /usr/bin/ld: /tmp/ccNUFQ8z.o: in function main': gethost.c:(.text+0x2ad): undefined reference to freehostent' collect2: error: ld returned 1 exit status 这个完全相同的源文件在 MacOS 10.14 上编译得很好。

标签: c networking linker


【解决方案1】:
../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 语句替换为它们的实际内容。你应该 能够通过这个 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 内核和许多系统 头文件。 netdb.h 中的 addrinfo 定义受到保护 像这样:

#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

当您使用 -ansi 标志运行 gcc 时,这会取消定义 __USE_POSIX 宏,因为受此保护的东西可能不是 严格符合ANSI。对比一下就能看出区别 这个:

gcc -E /usr/include/netdb.h

有了这个:

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

只有前者包含addrinfo 结构。

【讨论】:

  • 我得到与输出相同的三个头文件。我看到这些编译错误:pastebin.com/jVVMqftA
  • 所以...它工作了吗?也就是说,您没有看到与netdb.h 相关的任何错误,而您只是收到有关memset() 的警告?这听起来像是进步。 memset() 警告意味着您需要 #include &lt;string.h&gt;(这来自 memset(3) 手册页)。
  • 如果我也包含string.h,我看不到任何警告或错误。但是,我希望我的代码符合 ANSI C,所以我仍然遇到这些错误...pastebin.com/B21NyGQ9
  • 我已经更新了我的答案来解释发生了什么。如果您发现此讨论有帮助,请通过接受答案来表明这一点。
【解决方案2】:

在文件顶部添加

#define _XOPEN_SOURCE 600

【讨论】:

  • 谢谢!这行得通。问题在于这一行的存在:#define _POSIX_C_SOURCE 199309 并在其下方添加#define _XOPEN_SOURCE 600 即可修复它,而无需将其完全删除或将其更改为_GNU_SOURCE,这会过多地改变程序的含义。跨度>
【解决方案3】:

链接不会将头文件附加到程序中,预处理会处理头文件。

链接将共享对象库(在 /usr/lib 中查找)附加到编译对象。有时仅添加“-lnetdb”是不够的,因为库可能不在链接器路径中。在这种情况下,您需要使用 -L(path) 添加路径条目,以便指令“-lnetdb”可以找到正确的 netdb.so 文件。

【讨论】:

  • 我的文件夹中好像没有名为*netdb* 的共享对象...pastebin.com/9GPmFehC 如何获取我丢失的 SO 文件?
【解决方案4】:

使用#include &lt;netinet/in.h&gt; ....连同那个......并在编译中(ubuntu)......

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

(这里lpthread 是一个linki 处理线程)...解决了你的问题。 :-D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 2011-11-11
    • 2015-08-11
    相关资源
    最近更新 更多