Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588078
  • 博文数量: 50
  • 博客积分: 4764
  • 博客等级: 上校
  • 技术积分: 597
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-18 09:00
个人简介

资深IT码农,擅长Linux、C/C++、bash

文章分类

全部博文(50)

文章存档

2015年(17)

2014年(2)

2011年(7)

2010年(4)

2009年(20)

分类: C/C++

2011-09-14 10:42:18

缺少头文件导致的段错误

冷胜魁(Seaquester)
lengshengkui@gmail.com
2011-9-14

有这样一段简单的代码,在32位Linux(CentOS 6)下没有问题,但是,拿到64位Linux(CentOS 6)下运行就会出现段错误。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <netdb.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>


  6. int get_host_ip(const char* server)
  7. {
  8.     struct addrinfo *result = NULL;
  9.     int ret;
  10.     struct addrinfo addr;

  11.     memset(&addr, 0, sizeof(addr));
  12.     addr.ai_socktype = SOCK_STREAM;

  13.     ret = getaddrinfo(server, NULL, &addr, &result);
  14.     if (ret) {
  15.         perror("getaddrinfo");
  16.         return ret;
  17.     }

  18.     struct addrinfo *pCurr = result;
  19.     printf("%s:\n", server);
  20.     for (; pCurr; pCurr = pCurr->ai_next) {
  21.         printf("%s\n", inet_ntoa(((struct sockaddr_in*)(pCurr->ai_addr))->sin_addr));
  22.     }
  23.     printf("\n");

  24.     freeaddrinfo(result);
  25.     return 0;
  26. }


  27. int main()
  28. {
  29.     get_host_ip("localhost");
  30.     return 0;
  31. }

运行结果如下:

  1. [shengkui@uranus code]$ ./getaddr
  2. chinaunix.net:
  3. Segmentation fault (core dumped)
很奇怪,通过gdb来调试了一下:

  1. [shengkui@uranus code]$ gcc -g -o getaddr getaddr.c
  2. [shengkui@uranus code]$ gdb ./getaddr
  3. GNU gdb (GDB) Red Hat Enterprise Linux (7.1-29.el6)
  4. Copyright (C) 2010 Free Software Foundation, Inc.
  5. License GPLv3 : GNU GPL version 3 or later
  6. This is free software: you are free to change and redistribute it.
  7. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  8. and "show warranty" for details.
  9. This GDB was configured as "x86_64-redhat-linux-gnu".
  10. For bug reporting instructions, please see:
  11. ...
  12. Reading symbols from /home/shengkui/work/code/getaddr...done.
  13. (gdb) run
  14. Starting program: /home/shengkui/work/code/getaddr
  15. localhost:

  16. Program received signal SIGSEGV, Segmentation fault.
  17. 0x000000317a247fe7 in vfprintf () from /lib64/libc.so.6
  18. Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6.x86_64
  19. (gdb) bt
  20. #0 0x000000317a247fe7 in vfprintf () from /lib64/libc.so.6
  21. #1 0x000000317a24ef8a in printf () from /lib64/libc.so.6
  22. #2 0x0000000000400736 in get_host_ip (server=0x40088d "localhost") at getaddr.c:28
  23. #3 0x0000000000400774 in main () at getaddr.c:40
  24. (gdb) f 2
  25. #2 0x0000000000400736 in get_host_ip (server=0x40088d "localhost") at getaddr.c:28
  26. 28 printf("%s\n", inet_ntoa(((struct sockaddr_in*)(pCurr->ai_addr))->sin_addr));
  27. (gdb) quit
发现出错在 inet_ntoa 那一行。查看了 inet_ntoa 的帮助,没有发现什么特别的地方。
试着打开编译的warning开关看看有没有什么发现:

  1. [shengkui@uranus ~]$ gcc -g -o getaddr getaddr.c -Wall
  2. getaddr.c: In function 'get_host_ip':
  3. getaddr.c:26: warning: implicit declaration of function 'inet_ntoa'
  4. getaddr.c:26: warning: format '%s' expects type 'char *', but argument 2 has type 'int'
inet_ntoa 没有声明,是因为没有加必须的头文件。
inet_ntoa 的返回值是 “char *”, 而编译器似乎把它的返回值当成了int?是这个导致的错误吗?
在64位的Linux 下,int是32位的,而指针(在这里是 char *)是64位的。问题应该就是出在这里!

我把 inet_ntoa 需要的头文件加上去:
  1. #include
  2. #include
  3. #include
编译,运行,结果正确,没有段错误!

这个问题提醒我们,函数的声明不是可有可无的,不要小看任何一个warning。

阅读(6621) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~