您的位置:首页 > 其它

GDB学习:3

2016-01-14 10:31 363 查看
下面看一下观察点调试:

这里的例子如上所示:

#include<stdio.h>
int main(void)
{
int sum = 0, i = 0;
char input[5];
while (1) {
sum = 0;
scanf("%s", input);
for (i = 0; input[i] != '\0'; i++)
sum = sum*10 + input[i] - '0';
printf("input=%d\n", sum);

}
return 0;
}
这里输入超长可能就会出现问题:

1234567
input=1234567
12345678
input=123456740


下面使用gdb开始调试。
11	    int sum = 0, i = 0;
(gdb) n
14	        sum = 0;
(gdb)
15	        scanf("%s", input);


使用display打印出i以及input的值,这里输入的是12345678:

12345678
16	        for (i = 0; input[i] != '\0'; i++)
1: input = "12345"
(gdb)
17	        sum = sum*10 + input[i] - '0';
1: input = "12345"
(gdb)
16	        for (i = 0; input[i] != '\0'; i++)
1: input = "12345"
(gdb)
17	        sum = sum*10 + input[i] - '0';
1: input = "12345"
(gdb) display i
2: i = 1
(gdb) n
16	        for (i = 0; input[i] != '\0'; i++)
2: i = 1
1: input = "12345"
(gdb)
17	        sum = sum*10 + input[i] - '0';
2: i = 2
1: input = "12345"
(gdb)
16	        for (i = 0; input[i] != '\0'; i++)
2: i = 2
1: input = "12345"
(gdb)
17	        sum = sum*10 + input[i] - '0';
2: i = 3
1: input = "12345"
(gdb)
16	        for (i = 0; input[i] != '\0'; i++)
2: i = 3
1: input = "12345"
(gdb)
17	        sum = sum*10 + input[i] - '0';
2: i = 4
1: input = "12345"


单上这样看不到input周围内存的具体情况,这时可以使用x来打印具体的内存情况:

(gdb) x/10b input
0x7fffffffe010:	49	50	51	52	53	54	55	56
0x7fffffffe018:	4	0
x命令打印存储器中的内容。10b是打印格式,b表示每个字节一组,7表示打印10组 。前8个字节是i也就是i从0到6的循环都没错,我们设一个条件断点从i等于7开始

单步调试:

(gdb) b 17 if i == 7
Breakpoint 4 at 0x400592: file watch.c, line 17.
(gdb) c
Continuing.
12345678

Breakpoint 4, main () at watch.c:17
17	        sum = sum*10 + input[i] - '0';
2: i = 7
1: input = "12345"
可见到目前为止虽然数组越界了,但是还没有产生瞠目错误:

(gdb) display sum
3: sum = 1234567
继续单步,可以看到有一位莫名奇妙从7变成了8:

0x7fffffffe010:	49	50	51	52	53	54	55	56
0x7fffffffe018:	7	0
(gdb) n
17	        sum = sum*10 + input[i] - '0';
3: sum = 12345678
2: i = 8
1: input = "12345"
(gdb) x /10 input
0x7fffffffe010:	49	50	51	52	53	54	55	56
0x7fffffffe018:	8	0
为了看清这一位是何时改变的,i可以用观察点(Watchpoint)来跟踪。我们知道断点是当程序执行到某一代码行时中断,而观察点是当程序访问某一存储单元时中断,如果我们不知道某一存储单元是在哪里被改动的,这时候观察点尤其有用。下面删除原来设的断点,从头执行程序,重复上次的输入,用watch命令设置观察点,跟踪input[7]后面那个字节:

(gdb) watch input[8]
Hardware watchpoint 8: input[8]
(gdb) i watchpoints
Num     Type           Disp Enb Address            What
8       hw watchpoint  keep y                      input[8]
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 0 '\000'
New value = 1 '\001'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 1
2: i = 1
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 1 '\001'
New value = 2 '\002'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 12
2: i = 2
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 2 '\002'
New value = 3 '\003'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 123
2: i = 3
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 3 '\003'
New value = 4 '\004'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 1234
2: i = 4
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 4 '\004'
New value = 5 '\005'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 12345
2: i = 5
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 5 '\005'
New value = 6 '\006'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 123456
2: i = 6
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 6 '\006'
New value = 7 '\a'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 1234567
2: i = 7
1: input = "12345"
(gdb) c
Continuing.
Hardware watchpoint 8: input[8]

Old value = 7 '\a'
New value = 8 '\b'
0x00000000004005b9 in main () at watch.c:16
16	        for (i = 0; input[i] != '\0'; i++)
3: sum = 12345678
2: i = 8
1: input = "12345"


已经很明显了,每次都是for这句改变了input[5]的值,而且是每次加1,而for这句里的i正是每次加1的,原来input[5]就是i的存储单元,换句话说,i的存储单元是紧跟在input数组后面的。

小结一下上面看到的所有命令:

watch 设置观察点
info(或i)
watchpoints 查看当前设置了哪些观察点
x 从某个位置开始打印存储器的一段内容,全部当成字节来看,而
不区分哪些字节属于哪些变量
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: