今天来记录个小问题,应该说是个「坑」。
写了个 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_ntoa
,inet_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 |
|
善待警告
在老版本的 C (如 C98,C99
)语言中,如果你在使用 inet_ntoa
函数前没有 #include <arpa/inet.h>
,在某些 64
位系统上它的返回类型为 int
,%s
遇上 int
,怪不得会 segmentation fault
了……
这他妈真是个坑,也不知道是谁设计的,既然要 include
这三个文件才能用这个函数,那你就别让我编译通过给个 error
行不行?
这就回到了一个好的编程习惯的问题了:
不要忽略代码中出现的告警,有些警告其实就是错误。