C-gethostbyaddr& Valgrind的

时间:2010-11-29 23:21:33

标签: c valgrind

由于某种原因valgrind不断抛出以下错误:

==6263== Invalid read of size 4
==6263==    at 0x40151B9: (within /lib/ld-2.7.so)
==6263==    by 0x4005C29: (within /lib/ld-2.7.so)
==6263==    by 0x4007A47: (within /lib/ld-2.7.so)
==6263==    by 0x40114F3: (within /lib/ld-2.7.so)
==6263==    by 0x400D585: (within /lib/ld-2.7.so)
==6263==    by 0x4010F0D: (within /lib/ld-2.7.so)
==6263==    by 0x4141391: (within /lib/tls/i686/cmov/libc-2.7.so)
==6263==    by 0x400D585: (within /lib/ld-2.7.so)
==6263==    by 0x4141554: __libc_dlopen_mode (in /lib/tls/i686/cmov/libc-2.7.so)
==6263==    by 0x411B286: __nss_lookup_function (in /lib/tls/i686/cmov/libc-2.7.so)
==6263==    by 0x411B39F: (within /lib/tls/i686/cmov/libc-2.7.so)
==6263==    by 0x411CFC5: __nss_hosts_lookup (in /lib/tls/i686/cmov/libc-2.7.so)
==6263==  Address 0x4183d24 is 36 bytes inside a block of size 37 alloc'd
==6263==    at 0x4022AB8: malloc (vg_replace_malloc.c:207)

这是我正在做的方式。出现这种情况的原因是什么?感谢

#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>

char *IPtoHostname(const char *ipaddress)
{ 
    struct hostent *host;
    unsigned int ip = 0;
    ip = inet_addr (ipaddress);
    host = gethostbyaddr ((char *) &ip, sizeof (unsigned int), AF_INET);
    if (host == NULL) return NULL;
    return strdup(host->h_name);
}

int main () {
   const char *ip = "65.55.4.170";
   char *a =  NULL;
   a = IPtoHostname(ip);
   printf ("%s\n", a); 
   free (a);

   return 0;
}

更新:当我在Linux hardy 2.6.24-16-generic下运行它时会发生这种情况Ubuntu 9.10下不会发生

4 个答案:

答案 0 :(得分:2)

您的代码没问题(尽管您应该使用in_addr_t代替unsigned int来代替ip中的变量IPtoHostname()

Valgrind报告是well-known issue - 要么是误报,要么是glibc中的错误。

答案 1 :(得分:1)

消除这些遗留功能中的问题的一种方法是停止使用它们。截至2008年,gethostbynamegethostbyaddr已从POSIX移除;他们在IPv6支持,线程安全,不明确的规范和跨平台的不一致实现等方面存在严重问题。你根本就不应该使用它们。

现代替代品是getaddrinfogetnameinfo。如果你使用这些函数,你将永远不必像你一样编写丑陋的包装器。

答案 2 :(得分:0)

inet_addr并不总是返回简单的unsigned int。它返回一个in_addr_t(或in_addr,具体取决于你的C头的味道,我的linux 2.6.31 / glib 2.0)。在我的系统上,in_addr_t实际上是128位(16字节),因为inet_addr可以返回IPv6地址。

同样,gethostbyaddr需要in_addr_t,而不是unsigned int。这几乎肯定是你的问题。将ip的类型更改为inet_addr_t并更改相应的sizeof,并在下次更加关注编译器警告。

struct hostent *host;
in_addr_t ip = inet_addr(ipaddress);
host = gethostbyaddr (&ip, sizeof(ip), AF_INET);
if (host == NULL) return NULL;
return strdup(host->h_name);

答案 3 :(得分:-1)

您没有检查gethostbyaddr的返回值。
如果它返回 NULL 表示它无法获取主机名怎么办? 在这种情况下,您尝试取消引用 NULL 以致电strdup上的host->h_name
那显然会失败。