2010-11-29 2 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; 
} 

Update: Это происходит, когда я бегу под 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

Ваш код ОК (хотя вы действительно должны использовать in_addr_t вместо unsigned int переменной ip в IPtoHostname()).

Отчет Valgrind является well-known issue - либо ложным положительным, либо ошибкой в ​​glibc.

-1

Вы не проверять возвращаемое значение gethostbyaddr.
Что делать, если он возвращает NULL, указав, что он не смог получить имя хоста?
В этом случае вы пытаетесь снять ссылку NULL, чтобы позвонить по телефону strdup на номер host->h_name.
Это, очевидно, не удастся.

0

inet_addr не всегда возвращает простой unsigned int. Он возвращает in_addr_t (или in_addr в зависимости от вашего аромата заголовков C, linux 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

Одним из способов устранения проблемы в этих устаревших функциях является прекращение их использования. gethostbyname и gethostbyaddr были удалены из POSIX с 2008 года; они имеют серьезные проблемы с поддержкой IPv6, безопасностью потоков, нечеткой спецификацией и непоследовательной реализацией на разных платформах и т. д. Вы просто не должны их использовать.

Современные замены: getaddrinfo и getnameinfo. Если вы используете эти функции, вам никогда не придется писать уродливые обертки, как вы делаете.

Смежные вопросы