2010-05-25 12 views
6

Ho il seguente pezzo di codice per ottenere il nome host e l'indirizzo IP,Segmentation fault quando si cerca su nome host e l'indirizzo IP

#include <stdlib.h> 
#include <stdio.h> 
#include <netdb.h> /* This is the header file needed for gethostbyname() */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 


int main(int argc, char *argv[]) 
{ 
struct hostent *he; 

if (argc!=2){ 
printf("Usage: %s <hostname>\n",argv[0]); 
exit(-1); 
} 

if ((he=gethostbyname(argv[1]))==NULL){ 
printf("gethostbyname() error\n"); 
exit(-1); 
} 

printf("Hostname : %s\n",he->h_name); /* prints the hostname */ 
printf("IP Address: %s\n",inet_ntoa(*((struct in_addr *)he->h_addr))); /* prints IP address */ 
} 

Ma io sono sempre un avviso durante la compilazione:

$cc host.c -o host 
host.c: In function ‘main’: 
host.c:24: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’ 

Poi c'è un errore di segmentazione quando si esegue il codice:

./host 192.168.1.4 
Hostname : 192.168.1.4 
Segmentation fault 

Qual è l'errore nel codice?

+4

Stai facendo qualcosa di orribile a una struttura innocente. – SLaks

+0

A proposito, in generale non si dovrebbe usare 'gethostbyname' nel nuovo codice, soprattutto perché non è compatibile con IPv6. Dovresti invece usare 'getaddrinfo': http://beej.us/guide/bgnet/output/html/multipage/getaddrinfoman.html –

+0

Cosa succede se esegui ./host www.stackoverflow.com? Cioè, se lo usi con un nome reale piuttosto che un indirizzo IP. – nsayer

risposta

6

L'avviso relativo alla mancata corrispondenza per il formato printf è un avvertimento importante. In questo caso, viene perché il compilatore sta pensando che la funzione inet_ntoa restituisce un int, ma si è specificato di aspettarsi una stringa nella stringa formato.

La corretta return-tipo per inet_ntoa è il risultato di una vecchia regola C che afferma che se si tenta di utilizzare una funzione senza una dichiarazione preliminare, poi il compilatore deve assumere la funzione restituisce un int e prende uno sconosciuto (ma risolto) numero di argomenti. La mancata corrispondenza tra il tipo di ritorno presunto e il tipo di ritorno effettivo della funzione produce un comportamento non definito, che si manifesta come un arresto anomalo nel tuo caso.

La soluzione è includere l'intestazione corretta per inet_ntoa.

0

In realtà, ho appena compilato quel codice sul mio computer FreeBSD a casa e funziona.

+0

Ho provato senza #include su Mac OS e stava dando avvertimento e aveva un errore di segmentazione – Biranchi

0

Si potrebbe provare a scaricare il valore di he->h_addr prima di provare a dereferenziarlo e passarlo a inet_ntoa. Se fosse NULL, ciò comporterebbe un errore di seg.

Che ne dici di eseguirlo tramite strace?

1

rottura di questo codice:

printf("IP Address: %s\n",inet_ntoa(*((struct in_addr *)he->h_addr))); 

In questa:

struct in_addr* address = (in_addr*) he->h_addr; 
char* ip_address = inet_ntoa(*address); 
printf("IP address: %s\n", ip_address); 

E rende anche più facile eseguire il debug e individuare il problema.

8

Avevo un codice simile (se non uguale) e compilato correttamente in una macchina nel nostro laboratorio scolastico, ma quando l'ho compilato sulla mia macchina a casa, ha avuto lo stesso errore (non ho modificato il codice). Ho letto la pagina man per inet e ho riscontrato che mancava un file di intestazione, ovvero #include <arpa/inet.h>. Dopo aver aggiunto quell'intestazione al mio programma C, è stato compilato ed eseguito correttamente.

+1

ha funzionato per me. Molte grazie! –

Problemi correlati