2010-11-29 71 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。如果你使用這些函數,你永遠不會像你所做的那樣寫出醜陋的包裝器。