Chinaunix首页 | 论坛 | 博客
  • 博客访问: 875939
  • 博文数量: 149
  • 博客积分: 3671
  • 博客等级: 中校
  • 技术积分: 1701
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-03 16:52
文章分类

全部博文(149)

文章存档

2011年(57)

2010年(92)

分类: LINUX

2011-06-15 14:48:41

如果程序运行时出现段错误,用gdb可以很容易定位到究竟是哪一行引发的段错误,例如这个小程序:

例 10.4. 段错误调试实例一

#include int main(void) { int man = 0; scanf("%d", man); return 0; }

调试过程如下:

$ gdb main ... (gdb) r Starting program: /home/akaedu/main 123 Program received signal SIGSEGV, Segmentation fault. 0xb7e1404b in _IO_vfscanf () from /lib/tls/i686/cmov/libc.so.6 (gdb) bt #0 0xb7e1404b in _IO_vfscanf () from /lib/tls/i686/cmov/libc.so.6 #1 0xb7e1dd2b in scanf () from /lib/tls/i686/cmov/libc.so.6 #2 0x0804839f in main () at main.c:6

在gdb中运行,遇到段错误会自动停下来,这时可以用命令查看当前执行到哪一行代码了。gdb显示段错误出现在_IO_vfscanf函数中,用bt命令可以看到这个函数是被我们的scanf函数调用的,所以是scanf这一行代码引发的段错误。仔细观察程序发现是man前面少了个&。

继续调试上一节的程序,上一节最后提出修正Bug的方法是在循环中加上判断条件,如果不是数字就报错退出,不仅输入字母可以报错退出,输入超长的字符串也会报错退出。表面上看这个程序无论怎么运行都不出错了,但假如我们把while (1)循环去掉,每次执行程序只转换一个数:

例 10.5. 段错误调试实例二

#include int main(void) { int sum = 0, i = 0; char input[5]; scanf("%s", input); for (i = 0; input[i] != '\0'; i++) { if (input[i] < '0' || input[i] > '9') { printf("Invalid input!\n"); sum = -1; break; } sum = sum*10 + input[i] - '0'; } printf("input=%d\n", sum); return 0; }

然后输入一个超长的字符串,看看会发生什么:

$ ./main 1234567890 Invalid input! input=-1

看起来正常。再来一次,这次输个更长的:

$ ./main 1234567890abcdef Invalid input! input=-1 Segmentation fault

又出段错误了。我们按同样的方法用gdb调试看看:

$ gdb main ... (gdb) r Starting program: /home/akaedu/main 1234567890abcdef Invalid input! input=-1 Program received signal SIGSEGV, Segmentation fault. 0x0804848e in main () at main.c:19 19 } (gdb) l 14 } 15 sum = sum*10 + input[i] - '0'; 16 } 17 printf("input=%d\n", sum); 18 return 0; 19 }

gdb指出,段错误发生在第19行。可是这一行什么都没有啊,只有表示main函数结束的}括号。这可以算是一条规律,如果某个函数的局部变量发生访问越界,有可能并不立即产生段错误,而是在函数返回时产生段错误

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