Segmentation fault:inet_ntoa 崩溃咯

今天来记录个小问题,应该说是个「坑」。

写了个 socket 通信程序,在我 64 位的 Mac mini 上,调用 inet_ntoa 函数产生段错误 Segmentation fault: 11

出错的地方就在这行代码:

1
printf("accept a new client from: %s\n", inet_ntoa(client_addr.sin_addr));

把它注释再跑就 OK,干掉注释再跑又崩溃……试了好几次,每次都如此。

Surpried?!

inet_ntoa 把网络地址转换成字符串(如 192.168.8.168),返回 char *,我 printf%s 格式化它,应该没错啊……

后来,我发现编译时有几行信息都是关于这个 inet_ntoa 函数的:

看到了没,不仅 inet_ntoainet_aton 也相应地给出了警告,前面两行翻译成人话就是:

inet_aton 函数声明非法,inet_ntoa 函数声明非法。

更离谱的是,最后一行居然说类型不匹配,inet_ntoa 返回类型为 int

一瞬间,我凌乱了,学了这么多年的 C 语言,不知道这 inet_ntoa 玩的是哪一出啊。

man 一下 inet_ntoa 看,其中有一行特别重要:

These include files are necessary for all functions.

原来啊原来,这几个头文件都需要 include 进来!

而我的程序中,漏掉了最后一行 #include <arpa/inet.h>,赶紧加上,再编译、运行,呵呵~

感兴趣的,可以拿下面这个个小 Demo 感受下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
//#include <arpa/inet.h>

int main(int argc,char *argv[])
{
struct sockaddr_in cli_addr;
char *some_addr;

inet_aton("127.0.0.1", &cli_addr.sin_addr);

some_addr = inet_ntoa(cli_addr.sin_addr);
printf("%s\n", some_addr);

return 0;
}

善待警告

在老版本的 C (如 C98,C99)语言中,如果你在使用 inet_ntoa 函数前没有 #include <arpa/inet.h> ,在某些 64 位系统上它的返回类型为 int%s 遇上 int,怪不得会 segmentation fault了……

这他妈真是个坑,也不知道是谁设计的,既然要 include 这三个文件才能用这个函数,那你就别让我编译通过给个 error 行不行?

这就回到了一个好的编程习惯的问题了:

不要忽略代码中出现的告警,有些警告其实就是错误。

彦祖老师 wechat