调试中的很重要的一环就是断点了,下面来看看断点:
首先是测试程序:
#include<stdio.h>
int main(void)
{
int sum = 0, i = 0;
char input[5];
while (1) {
scanf("%s", input);
for (i = 0; input[i] != '\0'; i++)
sum = sum*10 + input[i] - '0';
printf("input=%d\n", sum);
}
return 0;
}
云心结果会发现第一次正确但是第二次错误:
root@wc:~/Codes/Learn/learnGDB# ./breakPoint
11
input=11
12
input=1112
下面开始调试,由于sum很可以,可以使用display直接将sum的值固定。
(gdb) display sum
1: sum = 0
(gdb) n
14 scanf("%s", input);
1: sum = 0
(gdb)
undisplay可以取消这个变量的显示。
实际上第一次结果错误,如果一直用n会很麻烦,说所以这里可以使用b(breakpoint)在scanf的位置打一个断点。
(gdb) b 14
Breakpoint 2 at 0x40056c: file breakPoint.c, line 14.
打完断点之后,就可以使用c(continue)来进行连续的运行而不是单步执行。
然后在两次连续运行之后,我们就会发现问题所在:
Breakpoint 2, main () at breakPoint.c:14
14 scanf("%s", input);
1: sum = 123123
(gdb)
会发现sum在输入123之后的值居然是123123,这也就说明了上一次运行之后的sum值没有删除,这也找到了问题所在。
使用info b(breakpoints)可以查看到到目前为止打上的所有的断点,其中每个断点都是有编号的
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040056c in main at breakPoint.c:14
breakpoint already hit 3 times
3 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
由于断点之间都是有编号来进行区分的,所以可以通过断点的编号来删除指定的断点:
(gdb) delete breakpoints 4
(gdb) delete breakpoints 5
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040056c in main at breakPoint.c:14
breakpoint already hit 3 times
3 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
6 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
7 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
8 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
或者也可以使用disable来暂时的禁用一个断点而无需去删除他:
(gdb) info breakpoints
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040056c in main at breakPoint.c:14
breakpoint already hit 3 times
3 breakpoint keep n 0x0000000000400582 in main at breakPoint.c:15
6 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
7 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
8 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
上面可以看到断点3没有被删除,但是起Enb标志实际上被置为n了。
gdb的断点不仅有上述的功能,还可以设置成为满足某个条件的时候才激活 ,对上面的例子,可以设置为仅仅当sum不等于0的时才去中断,然后使用r(run)命令重新从程序开头开始执行。
(gdb) break 9 if sum != 0
Breakpoint 9 at 0x40055e: file breakPoint.c, line 9.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Codes/Learn/learnGDB/breakPoint
123
Breakpoint 6, main () at breakPoint.c:15
15 for (i = 0; input[i] != '\0'; i++)
1: sum = 0
(gdb) i breakpoints
Num Type Disp Enb Address What
3 breakpoint keep n 0x0000000000400582 in main at breakPoint.c:15
6 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
breakpoint already hit 1 time
7 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
breakpoint already hit 1 time
8 breakpoint keep y 0x0000000000400582 in main at breakPoint.c:15
breakpoint already hit 1 time
9 breakpoint keep y 0x000000000040055e in main at breakPoint.c:9
stop only if sum != 0
上面可以看到在设置了break 9 if sum != 0之后,显示的最后一个breakpoint上的是 stop only if sum != 0。这也说明设置的条件正常生效了。
下面小结一下上面讲到的所有关于断点的操作:
break(或b) 行号 在某一行设置断点
break 函数名 在某个函数开头设置断点
break...if... 设置条件断点
continue(或c) 从当前位置开始连续而非单步执行程序
delete breakpoints 删除断点display 变量名 跟踪查看一个变量,每次停下来都显示它的值
disable breakpoints 禁用断点
enable breakpoints 启用断点
info(或i) breakpoints 查看当前设置了哪些断点
run(或r) 从头开始连续而非单步执行程序
undisplay 取消对先前设置的那些变量的跟踪