gdb 基本使用
本篇博客主要是对《LinuxC》相关章节中的学习笔记以及记录。在学习的过程中,为了减缓遗忘,以及将来需要时可以随时查阅自己的知识库,故整理如下。
单步执行和跟踪函数调用
首先写一段有问题的测试代码:
接下来,对于 gdb 的使用,我们主要是以调试这个程序的方式来理解。
结果显然错误。
然后我们来调试,
-g
的作用是在目标文件中加入源代码的信息,比如目标文件的机器指令对应源代码的第几行,但并不是把整个源文件嵌入到目标文件中。所以在调试目标文件时必须保证
gdb 也能找到源文件。
help
命令。
查看命令的类别。
help files
。
查看 files 类别下有那些命令可以用。
list 1
。
从第一行开始列出源代码。一次只列 10 行。
list
命令可以简写成为 l
。
list
。
接上一条,继续从 11 行列出源代码。
直接回车。
重复上一条命令。
l add_range
。
列出一个函数的源代码。
quit
。
退出 gdb 环境。
start
。
开始执行命令。
这表示停在 main 函数中变量定义之后的第一条语句处等待我们发命令,gdb 列出这条语句表示它还没执行,并且马上要执行。
next
(简写为n
)。
接上条。一条一条执行语句。
start
。
重新来过。
step
(简写为s
)。
进入函数中去执行。
backtrace
(简写为bt
)。
在函数中查看函数调用的栈帧。
info
(简写为i
)。
查看局部变量(locals)的值:
frame
(简写为f
)。
选择栈帧。
示例,查看 main 函数当前局部变量的值,先用 frame
命令选择 1 号栈帧然后再查看局部变量:
p
)。
打印变量的值。
示例,打印 sum 的值:
这里的 $1
表示 gdb 保存着这些中间结果,$
后面的编号会自动增长,在命令中可以用 $1、$2、$3
等编号代替相应的值。
finish
。
让程序一直运行到当前函数返回为止。
按:这里出了一个大问题,我现在的 mingw 中的 gdb 版本是
gdb8.1,在这个版本中,执行 finish
命令会直接退出
gdb!无奈之下,换了 mingw 的版本,现在继续整理。
按:改换了 gdb 版本之后,这个程序的第一个结果变得正确了。但是这不是很重要,我们只是需要理解其背后的逻辑。
接下来,继续调试:
然后发现 sum 有问题。
之后我们就可以退出 gdb 去修改程序了。
set
。
但是,我们也可以使用 set
命令去立刻把 sum
的值改过来,然后继续执行代码,继续调试,
修改变量的值也可以用 print
命令,我们可以用
print
来修改变量的值,或者调用函数:
按:printf
的返回值表示实际要打印的字符数,同时,这里要明确将 printf
的返回值 cast 成 int 类型。
命令 | 描述 |
---|---|
backtrace(或 bt) | 查看各级函数调用及参数 |
finish | 执行到当前函数返回,然后停下来等待命令 |
frame(或 f) 帧编号 | 选择栈帧 |
info(或 i) locals | 查看当前栈帧局部变量的值 |
list(或 l) | 列出源代码,接着上次的位置往下列,每次列 10 行 |
list 行号 | 列出从第几行开始的源代码 |
list 函数名 | 列出某个函数的源代码 |
next(或 n) | 执行下一行语句 |
print(或 p) | 打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
set var | 修改变量的值 |
start | 开始执行程序,停在 main 函数第一行语句前面等待命令 |
step(或 s) | 执行下一行语句,如果有函数调用则进入到函数中 |
断点
测试代码: