一、gdb的一些基础命令
l
:显示代码
l n
:跳转到当前代码页的第n行的代码
l filename.c :n
:跳转到filename.c文件的第n行代码
b 行号
:加断点
info break
:查看断点信息
delete 断点编号
:删除断点
r
,运行程序
n
,单步执行
c
,继续执行,遇到断点停止执行
p
,打印
s
,进入函数
finish
,退出函数
q
,退出gdb
二、调试示例
先写一个main.c程序,该程序用来循环输出从键盘输入的字符串,直到遇到"end"结束循环:
编译并运行main.c:
发现和我们的预期并不一样,在输入"end"之后并没有结束循环,通过Ctrl+c结束这个进程。
- 进入gdb,gdb去调试Release版本:
从上图可以看出目前并不可以进行调试,之所以能打出一些信息,是因为这些信息是gdb打印出来的,而main程序还没有执行,下面的这句话
告诉我们在main程序中没有找到合适的符号,也就是没有包含调试信息,所以这个时候是调试不了的。在输入l
进行显示代码时,下面这句话
告诉我们没有调试的符号表示被导入。说明这时的main程序是有问题的,没有包含调试信息。输入q退出gdb。
- gdb去调试Debug版本:
(1)编译和跟踪
按照gcc -o main main.c -g
去编译main.c生成可执行程序main,并用gdb去跟踪main程序:
这时我们可以通过
这句话看出gdb从main中读到了符号表。
(2)显示所编写的代码
通过gdb指令l
显示代码
一次只能显示10行代码。
(3)设置断点
语法形式:break 行号
,break可以简写为b
将断点加到第13行:
可以继续下断点:
查看加了哪些断点info break
:
删除断点delete Num
:
删除第2个断点:
(4)运行程序进行调试
输入run
,可以简写为r
,按回车:
当前程序执行到了13行停止。
输入n
,让程序单步执行:
从上图可以看出输入了字符串"hello",然后程序运行到了17行的if语句。
这时,我们输入p buff
来查看一些buff中的内容:
可以看到,当前buff中存放的是字符串"hello\n"。
继续输入n
单步执行:
当前程序又执行到了13行。
我们继续单步执行,这次输入字符串"end",程序跳转到17行的if语句:
此时,我们再输入p buff
来查看一些buff中的内容:
可以看到,当前buff中存放的是字符串"end\n",这和我们输入的字符串"end"并不相同。
因此,再继续执行时,程序依然会进入循环:
此时,我们就通过调试发现了代码中存在的问题。
- 退出gdb
输入q
退出gdb,此时会提示如果要退出会杀死刚刚的main程序,是否要退出,输入y
表示退出,按回车就退出gdb。
退出gdb之后,刚刚的main程序也就结束了:
- 通过调试结果修正代码
将strcmp()改为strncmp():
此时,我们再去编译main.c,执行main程序,结果如下: