Chinaunix首页 | 论坛 | 博客
  • 博客访问: 149777
  • 博文数量: 23
  • 博客积分: 546
  • 博客等级: 中士
  • 技术积分: 608
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-02 18:04
文章分类

全部博文(23)

文章存档

2012年(23)

我的朋友

分类: LINUX

2012-07-10 11:57:54

观察点:

 

点击(此处)折叠或打开

1.  #include <stdio.h>

2.   

3.  int main(void)

4.  {

5.  int sum = 0, i = 0;

6.  char input[5];

7.   

8.  while (1) {

9.  sum = 0;

10. scanf("%s", input);

11. for (i = 0; input[i] != '\0'; i++)

12. sum = sum*10 + input[i] - '0';

13. printf("input=%d\n", sum);

14. }

15. return 0;

16. }

 

点击(此处)折叠或打开

1.  $ gdb main

2.  ...

3.  (gdb) start

4.  Breakpoint 1 at 0x80483b5: file main.c, line 5.

5.  Starting program: /home/akaedu/main

6.  main () at main.c:5

7.  5 int sum = 0, i = 0;

8.  (gdb) n

9.  9 sum = 0;

10. (gdb) (直接回车)

11. 10 scanf("%s", input);

12. (gdb) (直接回车)

13. 12345

14. 11 for (i = 0; input[i] != '\0'; i++)

15. (gdb) p input

16. $1 = "12345"

input数组只有5个元素,写出界的是scanf自动添的'\0',用x命令看会更清楚一些

 

点击(此处)折叠或打开

1.  (gdb) x/7b input

2.  0xbfb8f0a7: 0x31 0x32 0x33 0x34 0x35 0x00 0x00


x命令打印指定存储单元的内容。7b是打印格式,b表示每个字节一组,7表示打印7[],从input数组的第一个字节开始连续打印7个字节。前5个字节是input数组的存储单元,打印的正是十六进制ASCII码的'1''5',第6个字节是写出界的'\0'。根据运行结果,前4个字符转成数字都没错,第5个错了,也就是i03的循环都没错,我们设一个条件断点从i等于4开始单步调试:

 

点击(此处)折叠或打开

1.  (gdb) l

2.  6 char input[5];

3.  7

4.  8 while (1) {

5.  9 sum = 0;

6.  10 scanf("%s", input);

7.  11 for (i = 0; input[i] != '\0'; i++)

8.  12 sum = sum*10 + input[i] - '0';

9.  13 printf("input=%d\n", sum);

10. 14 }

11. 15 return 0;

12. (gdb) b 12 if i == 4

13. Breakpoint 2 at 0x80483e6: file main.c, line 12.

14. (gdb) c

15. Continuing.

16.  

17. Breakpoint 2, main () at main.c:12

18. 12 sum = sum*10 + input[i] - '0';

19. (gdb) p sum

20. $2 = 1234

现在sum1234没错,根据运行结果是123407我们知道即将进行的这步计算肯定要出错,算出来应该是12340,那就是说input[4]肯定不是'5'了,事实证明这个推理是不严谨的:

点击(此处)折叠或打开

1.  (gdb) x/7b input

2.  0xbfb8f0a7: 0x31 0x32 0x33 0x34 0x35 0x04 0x00


从头执行程序,重复上次的输入,用watch命令设置观察点,跟踪input[4]后面那个字节(可以用input[5]表示,虽然这是访问越界)

 

点击(此处)折叠或打开

1.  (gdb) delete breakpoints

2.  Delete all breakpoints? (y or n) y

3.  (gdb) start

4.  Breakpoint 1 at 0x80483b5: file main.c, line 5.

5.  Starting program: /home/akaedu/main

6.  main () at main.c:5

7.  5 int sum = 0, i = 0;

8.  (gdb) n

9.  9 sum = 0;

10. (gdb) (直接回车)

11. 10 scanf("%s", input);

12. (gdb) (直接回车)

13. 12345

14. 11 for (i = 0; input[i] != '\0'; i++)

15. (gdb) watch input[5]

16. Hardware watchpoint 2: input[5]

17. (gdb) i watchpoints

18. Num Type Disp Enb Address What

19. 2 hw watchpoint keep y input[5]

20. (gdb) c

21. Continuing.

22. Hardware watchpoint 2: input[5]

23.  

24. Old value = 0 '\0'

25. New value = 1 '\001'

26. 0x0804840c in main () at main.c:11

27. 11 for (i = 0; input[i] != '\0'; i++)

28. (gdb) c

29. Continuing.

30. Hardware watchpoint 2: input[5]

31.  

32. Old value = 1 '\001'

33. New value = 2 '\002'

34. 0x0804840c in main () at main.c:11

35. 11 for (i = 0; input[i] != '\0'; i++)

36. (gdb) c

37. Continuing.

38. Hardware watchpoint 2: input[5]

39.  

40. Old value = 2 '\002'

41. New value = 3 '\003'

42. 0x0804840c in main () at main.c:11

43. 11 for (i = 0; input[i] != '\0'; i++)

已经很明显了,每次都是回到for循环开头的时候改变了input[5]的值,而且是每次加1,而循环变量i正是在每次回到循环开头之前加1,原来input[5]就是变量i的存储单元,换句话说,i的存储单元是紧跟在input数组后面的。

本章学习的命令:

命令

描述

watch

设置观察点

info(或i watchpoints

查看当前设置了哪些观察点

x

从某个位置开始打印存储单元的内容,全部当成字节来看,而不区分哪个字节属于哪个变量

 

 

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