2010-05-25 3 views
6

У меня есть следующий фрагмент кода для получения имени хоста и IP-адрес,вина Сегментация при поиске имени хоста и 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 */ 
} 

Но я получаю предупреждение во время компиляции:

$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’ 

Тогда есть ошибка сегментации, когда я запускаю код:

./host 192.168.1.4 
Hostname : 192.168.1.4 
Segmentation fault 

Что такое ошибка в коде?

+4

Вы делаете что-то ужасное для невинной структуры. – SLaks

+0

Кстати, вы вообще не должны использовать 'gethostbyname' в новом коде, в основном потому, что он несовместим с IPv6. Вместо этого вы должны использовать 'getaddrinfo': http://beej.us/guide/bgnet/output/html/multipage/getaddrinfoman.html –

+0

Что произойдет, если вы запустите ./host www.stackoverflow.com? То есть, если вы используете его с фактическим именем, а не с IP-адресом. – nsayer

ответ

6

Предупреждение о несоответствии формата printf является важным предупреждением. В этом случае это происходит потому, что компилятор думает, что функция inet_ntoa возвращает int, но вы указали, что ожидаете строку в формате-string.

Неправильный тип возвращаемого значения для inet_ntoa является результатом старого правила C, в котором говорится, что если вы попытаетесь использовать функцию без предварительного объявления, то компилятор должен предположить, что функция возвращает int и принимает неизвестное (но фиксированное) количество аргументов. Несоответствие между предполагаемым типом возвращаемого значения и фактическим типом возврата функции приводит к неопределенному поведению, которое проявляется как крах в вашем случае.

Решение состоит в том, чтобы включить правильный заголовок для inet_ntoa.

0

На самом деле, я просто скомпилировал этот код на своей машине FreeBSD дома, и он работает.

+0

Я пробовал без #include на Mac OS, и он предупреждал и имел ошибку сегментации – Biranchi

0

Вы можете попробовать сбросить значение he->h_addr, прежде чем пытаться разыменовать его и передать его inet_ntoa. Если это было NULL, это приведет к ошибке seg.

Как насчет запуска через strace?

1

Перерыв этот код:

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

В это:

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

Это также облегчает отладку и точно определить проблему.

8

У меня был аналогичный код (если он не тот же), и он скомпилирован в машине в нашей школьной лаборатории, но когда я скомпилировал его на своей машине дома, у него была такая же ошибка (я не редактировал код). Я прочитал справочную страницу для inet и обнаружил, что у меня не было одного файла заголовка, который является #include <arpa/inet.h>. После того, как я добавил этот заголовок в свою программу на языке C, он скомпилирован и работает нормально.

+1

Работал для меня. Большое спасибо! –

Смежные вопросы