2010-11-29 1 views
2

Aus irgendeinem Grund valgrind hält den folgenden Fehler zu werfen: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) 

Hier ist die Art, wie ich es mache. Irgendwelche Gründe, warum das passiert? Dank

#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; 
} 

aktualisieren: Es passiert, wenn ich es unter Linux hardy 2.6.24-16-generic laufen Es geschieht nicht unter Ubuntu 9.10

+1

vg_replace_malloc existiert nur innerhalb valgrind – thkala

+0

Sie Ihr Programm mit -O0 -g kompiliert haben, nicht wahr? – thkala

+0

@thkala: Ich kompiliert mit: 'gcc -Wall -O0 -g prog.c' – RichardThomson

Antwort

2

Ihr Code in Ordnung ist (obwohl Sie wirklich in_addr_t verwenden sollten statt unsigned int für die Variable ip in IPtoHostname()).

Der Valgrind Bericht ist ein well-known issue - entweder ein falsch positive oder ein Fehler in glibc.

-1

Sie sind nicht den Rückgabewert von gethostbyaddr überprüfen.
Was passiert, wenn es NULL zurück darauf hinweist, dass es nicht in der Lage war, die Hostnamen zu bekommen?
In diesem Fall versuchen Sie, NULL zu de-referenzieren strdup auf dem host->h_name zu rufen.
Das wird offensichtlich fehlschlagen.

+1

Das ist richtig, aber ich denke, in diesem speziellen Fall wird es immer noch den gleichen Fehler werfen. (Überprüfung/nicht auf NULL prüfen) – RichardThomson

+0

Haben Sie Beweise dafür, dass gethostbyaddr NICHT fehlschlägt? Woher wissen Sie, dass der Name erfolgreich aufgelöst wird, wenn Sie das Ergebnis nicht überprüfen? – abelenky

+0

Sie überprüfen Ihre Rückgabewerte, ich bin zu beschäftigt mit dem Downvoting Sie -.- – Blindy

0

inet_addr gibt nicht immer eine einfache unsigned int zurück. Es gibt eine (oder eine in_addr abhängig von Ihrem Geschmack von C-Headern, meines Linux 2.6.31/glib 2.0) zurück. Auf meinem System ist eigentlich ein 128 Bit (16 Byte), weil inet_addr eine IPv6-Adresse zurückgeben kann.

In ähnlicher Weise nimmt gethostbyaddr eine , nicht eine unsigned int. Das ist fast sicher dein Problem. Ändern Sie den Typ von ip-inet_addr_t und ändern Sie die entsprechenden sizeof und mehr Aufmerksamkeit schenken, um Warnungen beim nächsten Mal Compiler.

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

Danke für die Info. Allerdings immer noch das gleiche Problem. Ich fange an zu denken, dass es etwas mit 'gethostbyaddr() 'zu tun hat. – RichardThomson

+1

[POSIX definiert' in_addr_t' als] (http://www.opengroup.org/onlinepubs/009695399/basedefs/netinet/in.h. html) * "Entspricht dem Typ" uint32_t "wie in' 'definiert." * Wenn Ihr System dies tut, ist es nicht POSIX-konform. 'in_addr_t' ist IPv4-spezifisch (wie auch' inet_addr() '). – caf

+0

@caf: In der Tat. Ich habe noch nie von einem System mit 128-Bit 'in_addr_t' gehört, und natürlich wäre es nicht konform. –

1

Eine Möglichkeit, das Problem in diesen Legacy-Funktionen zu beseitigen ist, sie zu stoppen. gethostbyname und gethostbyaddr wurden ab 2008 aus POSIX entfernt; Sie haben ernsthafte Probleme mit IPv6-Unterstützung, Thread-Sicherheit, unklarer Spezifikation und inkonsistenter plattformübergreifender Implementierung und so weiter. Du solltest sie einfach nicht benutzen.

Die modernen Ersatzteile sind getaddrinfo und getnameinfo. Wenn Sie diese Funktionen verwenden, müssen Sie nie hässliche Wrapper schreiben, wie Sie es tun.