Segmentation fault wenn Hostnamen und die IP-Adresse aufzuzublicken
Frage
Ich habe das folgende Stück Code für das Erhalten der Hostnamen und IP-Adresse,
#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 */
}
Aber ich bin eine Warnung während der Kompilierung bekommen:
$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’
Dann gibt es einen Segmentierungsfehler, wenn ich den Code ausführen:
./host 192.168.1.4
Hostname : 192.168.1.4
Segmentation fault
Was ist der Fehler im Code?
Lösung
Die Warnung über die Nichtübereinstimmung für das printf-Format ist eine wichtige Warnung.
In diesem Fall kommt es, weil der Compiler denkt, dass die Funktion inet_ntoa
eine int
zurückgibt, aber Sie angegeben eine Zeichenfolge im Format-String zu erwarten.
Die falsche Rückgabetyp für inet_ntoa
ist das Ergebnis einer alten C-Regel die besagt, dass, wenn Sie versuchen, eine Funktion ohne vorherige Anmeldung zu verwenden, wird der Compiler die Funktion übernehmen muss eine int
zurückgibt und eine unbekannte (aber fixiert ) Anzahl von Argumenten.
Die Diskrepanz zwischen dem angenommenen Rückgabetyp und der tatsächlichen Rückgabetyp der Funktion führt zu undefinierten Verhalten, was sich als ein Absturz in Ihrem Fall.
Die Lösung ist die richtigen Header für inet_ntoa
aufzunehmen.
Andere Tipps
Ich hatte einen ähnlichen Code (wenn nicht gleich) und es gut in unserem Schullabor in einer Maschine zusammengestellt, aber wenn ich es auf meinem Rechner zu Hause zusammengestellt, es hatte den gleichen Fehler (ich habe den Code nicht bearbeiten ). Ich las die Manpage inet
, und fand, dass ich eine Header-Datei hatte fehlt, was der #include <arpa/inet.h>
ist. Nachdem ich diesen Header meiner C-Programm hinzugefügt, es kompiliert und ausgeführt in Ordnung.
Break diesen Code:
printf("IP Address: %s\n",inet_ntoa(*((struct in_addr *)he->h_addr)));
In diesen:
struct in_addr* address = (in_addr*) he->h_addr;
char* ip_address = inet_ntoa(*address);
printf("IP address: %s\n", ip_address);
Es macht es auch einfacher zu debuggen und lokalisieren, das Problem.
Eigentlich habe ich gerade kompiliert, dass Code auf meinem FreeBSD-Rechner zu Hause und es funktioniert.
Sie könnten versuchen, den Wert von he->h_addr
Dumping bevor Sie versuchen, es zu dereferenzieren und es inet_ntoa
passieren. Wenn es NULL
ist, dass in einem seg Fehler führen würde.
Wie wäre es durch strace
läuft?