【问题标题】:correct usage of getaddrinfo and getnameinfo正确使用 getaddrinfo 和 getnameinfo
【发布时间】:2014-07-06 03:28:39
【问题描述】:

在我的 C 程序中,我使用 getaddrinfo 从主机名获取 IP 地址,并使用 getnameinfo 从 IP 地址获取主机名。这两个功能是互补的。我在man getaddrinfo 中读到,我必须使用freeaddrinfo() 函数来释放为动态分配的链表res 分配的内存。因此我的代码如下所示:

if ((err = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
  printf("error %d\n", err);
  return 1;
}

addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
printf("%s\n", inet_ntoa(addr));

freeaddrinfo(res);

但是对于getnameinfo,我没有看到任何类似的功能,即freenameinfo

为什么我在使用getaddrinfo 时需要释放而不是getnameinfo。为什么我需要完全释放?早些时候,当我使用gethostbyaddr 时,不需要释放内存。为什么这不一样。

getaddrinfogethostbyaddr 有什么优势?后者是否已弃用,只应使用前者?为什么?

【问题讨论】:

标签: c tcp ip


【解决方案1】:

getaddrinfo 的手册页,它返回给您一个动态分配的链表。 由于它执行了内存分配,因此它也会处理空闲内存是有道理的。

freeaddrinfo() 函数释放分配给它的内存 动态分配的链表资源。

另请注意,函数签名包含struct addrinfo **,这是一个很好的提示,表明库函数正在代表您进行分配并将指针返回给您。

   int getaddrinfo(const char *node, const char *service,
                       const struct addrinfo *hints,
                       struct addrinfo **res);

对于getnameinfo(),它需要调用者(你)分配const struct sockaddr *,所以释放它是调用者(你)的责任,并且没有相应的库调用来释放它。

   int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                   char *host, size_t hostlen,
                   char *serv, size_t servlen, int flags);

gethostbyaddr 的手册页中,它声明自己已被弃用。

gethostbyname*()、gethostbyaddr*()、herror() 和 hstrerror() 功能已过时。应用程序应使用 getaddrinfo(3), getnameinfo(3) 和 gai_strerror(3) 代替。

此时,我通常会停止阅读,不再使用gethostbyaddr,而是更喜欢getaddrinfo

为什么不推荐使用这些函数? 可能有很多原因,但Wikipedia 告诉我们旧版函数不支持IPv6,正如@R.. 在下面提到的,它们是not 线程安全的。

【讨论】:

  • @R..,谢谢我找到了参考并更新了答案。
  • getaddrinfo 是否需要在出错时释放内存?我在任何地方都看不到这些信息。我有一个使用它的程序,唯一没有调用 free 的地方是出错,valgrind 抱怨内存丢失。
  • @TheQuantumPhysicist,我真的不确定。如果在任何地方都没有记录,则很可能必须咨询the source
  • @merlin2011 这很合理。感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 2012-12-11
  • 2018-03-19
  • 2011-08-22
  • 1970-01-01
  • 2015-02-18
相关资源
最近更新 更多