2010-11-29 53 views
2

出于某种原因valgrind不断抛出以下错误:C- gethostbyaddr&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

+1

vg_replace_malloc仅存的valgrind – thkala 2010-11-29 23:33:25

+0

你编译程序用-O0 -g,对不对? – thkala 2010-11-29 23:56:26

+0

@thkala:我编译时使用了:`gcc -Wall -O0 -g prog.c` – RichardThomson 2010-11-30 00:00:35

回答

2

你的代码是OK(虽然你确实应该使用in_addr_t代替unsigned int为变量ipIPtoHostname())。

的Valgrind的报告是一个well-known issue - 无论是假阳性或glibc的一个bug。

-1

你是不是检查gethostbyaddr返回值它发生。
如果它返回NULL 表明它无法获取主机的名称?
在这种情况下,你试图去参考NULL调用strduphost->h_name
这显然会失败。

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); 
1

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

现代置换是getaddrinfogetnameinfo。如果你使用这些函数,你永远不会像你所做的那样写出丑陋的包装器。