2010-11-29 17 views
2

Pour une raison valgrind garde jeter l'erreur suivante: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) 

est le chemin Ici, je le fais. Des raisons pour lesquelles cela se produit? Merci

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

Mise à jour: Il arrive quand je le lance en Linux hardy 2.6.24-16-generic Il ne se produit pas sous Ubuntu 9.10

+1

vg_replace_malloc existe seulement dans valgrind – thkala

+0

Vous avez compilé votre programme avec -O0 -g, non? – thkala

+0

@thkala: J'ai compilé avec: 'gcc -Wall -O0 -g prog.c' – RichardThomson

Répondre

2

Votre code est correct (bien que vous devriez vraiment utiliser in_addr_t au lieu de unsigned int pour la variable ip dans IPtoHostname()).

Le rapport Valgrind est un well-known issue - un faux positif ou un bogue dans la glibc.

-1

Vous n'êtes pas vérifier la valeur de retour de gethostbyaddr.
Et s'il retourne NULL indiquant qu'il n'a pas pu obtenir le nom d'hôte?
Dans ce cas, vous essayez de dé-référencer NULL pour appeler strdup sur le host->h_name.
Cela échouera évidemment.

+1

C'est correct, cependant, je pense que dans ce cas particulier, il va encore lancer la même erreur. (vérifiant/ne vérifiant pas pour la valeur NULL) – RichardThomson

+0

Avez-vous des preuves que gethostbyaddr n'échoue PAS? Comment savez-vous qu'il réussit à résoudre le nom si vous ne vérifiez pas le résultat? – abelenky

+0

Vous vérifiez vos valeurs de retour, je suis trop occupé downvoting vous -.- – Blindy

0

inet_addr ne retourne pas toujours un simple unsigned int. Il renvoie un in_addr_t (ou un in_addr en fonction de votre saveur d'en-têtes C, le mien Linux 2.6.31/glib 2.0). Sur mon système, in_addr_t est en fait un 128 bits (16 octets) car inet_addr peut renvoyer une adresse IPv6.

De même, gethostbyaddr prend un in_addr_t, et non un unsigned int. C'est presque certainement votre problème. Changez le type de ip en inet_addr_t et modifiez le sizeof correspondant, et accordez plus d'attention aux avertissements du compilateur la prochaine fois.

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

Merci pour l'info. Cependant, toujours le même problème. Je commence à penser qu'il pourrait avoir quelque chose à faire avec 'gethostbyaddr()' – RichardThomson

+1

[POSIX définit 'in_addr_t' comme] (http://www.opengroup.org/onlinepubs/009695399/basedefs/netinet/in.h. html) * "Equivalent au type' uint32_t' tel que défini dans ''. "*, donc si votre système le fait, alors il n'est pas conforme à POSIX. 'in_addr_t' est spécifique à IPv4 (tout comme' inet_addr() '). – caf

+0

@caf: En effet. Je n'ai jamais entendu parler d'un système avec 'in_addr_t' 128 bits, et bien sûr, ce serait non-conforme. –

1

Une façon d'éliminer le problème dans ces fonctions héritées est d'arrêter de les utiliser. gethostbyname et gethostbyaddr ont été retirés de POSIX à partir de 2008; ils ont de sérieux problèmes avec le support IPv6, la sécurité des threads, les spécifications peu claires et la mise en œuvre incohérente sur toutes les plates-formes, etc. Vous ne devriez tout simplement pas les utiliser. Les remplacements modernes sont getaddrinfo et getnameinfo. Si vous utilisez ces fonctions, vous n'aurez jamais à écrire des wrappers laids comme vous le faites.