开发者

C- gethostbyaddr & Valgrind

For some reason valgrind keeps throwing the following error:

==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)

Here is the way I'm doing it. Any reasons why this is happe开发者_JAVA百科ning? Thanks

#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: It happens when I run it under Linux hardy 2.6.24-16-generic It does not happen under Ubuntu 9.10


Your code is OK (although you should really be using in_addr_t instead of unsigned int for the variable ip in IPtoHostname()).

The Valgrind report is a well-known issue - either a false positive or a bug in glibc.


One way to eliminate the problem in these legacy functions is to stop using them. gethostbyname and gethostbyaddr have been removed from POSIX as of 2008; they have serious issues with IPv6 support, thread-safety, unclear specification and inconsistent implementation across platforms, and so on. You simply should not use them.

The modern replacements are getaddrinfo and getnameinfo. If you use these functions, you'll never have to write ugly wrappers like you're doing.


inet_addr doesn't always return a simple unsigned int. It returns an in_addr_t (or an in_addr depending on your flavor of C headers, mine's linux 2.6.31 / glib 2.0). On my system, in_addr_t is actually a 128 bits (16 bytes) because inet_addr can return an IPv6 address.

Likewise, gethostbyaddr takes an in_addr_t, not an unsigned int. This is almost certainly your problem. Change the type of ip to inet_addr_t and change the corresponding sizeof, and pay more attention to compiler warnings next time.

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


You aren't checking the return value of gethostbyaddr.
What if it returns NULL indicating that it was unable to get the host name?
In that case, you try to de-reference NULL to call strdup on the host->h_name.
That will obviously fail.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜