C- gethostbyaddr & Valgrind - PullRequest
       2

C- gethostbyaddr & Valgrind

2 голосов
/ 30 ноября 2010

По какой-то причине 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 ]

2 голосов
/ 30 ноября 2010

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

Отчет Valgrind представляет собой well-известная проблема - либо ложное срабатывание, либо ошибка в glibc.

1 голос
/ 30 ноября 2010

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

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

0 голосов
/ 30 ноября 2010

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);
0 голосов
/ 30 ноября 2010

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

...