我有以下代码来获取主机名和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
代码中的错误是什么?
答案 0 :(得分:8)
我有一个类似的代码(如果不一样),它在我们学校实验室的机器上编译得很好,但是当我在家里的机器上编译它时,它有同样的错误(我没有编辑代码)。我阅读了inet
的手册页,发现我丢失了一个头文件,即#include <arpa/inet.h>
。将该标题添加到我的C程序后,它编译并运行正常。
答案 1 :(得分:6)
有关printf格式不匹配的警告是一个重要的警告。
在这种情况下,它是因为编译器认为函数inet_ntoa
返回int
,但您指定期望格式字符串中的字符串。
inet_ntoa
的错误返回类型是旧C规则的结果,该规则声明如果尝试使用没有事先声明的函数,则编译器必须假定函数返回{{1}并且获取一些未知(但固定)的参数。
假定的返回类型与函数的实际返回类型之间的不匹配会导致未定义的行为,这表现为您的案例中的崩溃。
解决方案是包含int
的正确标头。
答案 2 :(得分: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);
它还使调试和查明问题变得更加容易。
答案 3 :(得分:0)
实际上,我刚刚在家里的FreeBSD机器上编译了这段代码,但它确实有效。
答案 4 :(得分:0)
您可以尝试转储he->h_addr
的值,然后再尝试取消引用它并将其传递给inet_ntoa
。如果是NULL
,则会导致seg错误。
如何通过strace
运行它?