最近发现一个64位机器上出现段错误的问题。
现象:
执行如下的代码,在32位的机器上是OK的,但是64位出现了段错误。
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char * argv[])
{
struct in_addr addr;
char *p;
int i =0;
struct hostent *pHost = gethostbyname("www.baidu.com");
if (!pHost) {
return 0;
}
while(1)
{
p = pHost->h_addr_list[i];
if (NULL == p) {
break;
}
memcpy(&addr.s_addr, p, pHost->h_length);
printf("pHost->h_length = %d %ld\n", pHost->h_length, addr.s_addr);
printf("Address -> %s \n", inet_ntoa(addr));
}
return 0;
}
执行结果:
[liangdongsheng@routinggroup linux]$ make test
cc test.c -o test
[liangdongsheng@routinggroup linux]$ ./test
pHost->h_length = 4 1892937587
段错误 (core dumped)
[liangdongsheng@routinggroup linux]$ gdb ./test
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/liangdongsheng/linux/test...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/liangdongsheng/linux/test
pHost->h_lenght = 4 466808691
Program received signal SIGSEGV, Segmentation fault.
0x00000037b8447dec in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.x86_64
(gdb) backtrace
#0 0x00000037b8447dec in vfprintf () from /lib64/libc.so.6
#1 0x00000037b844f14a in printf () from /lib64/libc.so.6
#2 0x000000000040065c in main ()
(gdb)
gdb调试发现问题出现在printf函数上。
继续排查,修改如下
printf("pHost->h_length = %d %ld\n", pHost->h_length, addr.s_addr);
char *paddr = inet_ntoa(addr);
printf("Address -> %s \n", paddr);
编译时出现了警告:
cc test.c -o test
test.c: 在函数‘main’中:
test.c:26: 警告:初始化时将整数赋给指针,未作类型转换
结论:
原来在使用inet_ntoa()函数上,没有加入头文件#include <arpa/inet.h>导致编译时生成了一个inet_ntoa的默认链接符号,其返回值为整数型。
而int 型在64位的机器上是4个字节,指针类型为8个字节。最终应该是8个字节的地址被截取了4个字节,出现了段错误。