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.
精彩评论