🌞gdb的启动
准备内容
一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:
对于.c文件:
gcc -g -o hello hello.c
对于.cpp文件:
g++ -g -o hello hello.cpp
启动GDB的方法有以下几种:
- gdb program
program 也就是你的可执行文件,一般在当前目录下。 - gdb program core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。 - gdb program 1234
如果程序是一个服务程序,那么可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。
GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb的help查看。
🌞gdb技巧
🌼1. gdb小技巧汇总
gdb技巧挺多的,比如说直接回车是继续执行上一次的代码
巧用tab补全
1. 比如输入b连续按下两次tab,可以查看gdb的所有b开头的gdb指令
2. 比如设置断点记不清函数名称,举个简单示例:希望b main 但由于记不清main的函数全称,在b ma之后连续按下两次tab,可以查看ma开头的所有函数名称。
TUI 模式:GDB 的界面会分为几个窗格,包括源代码窗格、汇编窗格、寄存器窗格等。
按下ctrl x a会显示下图的窗口(可以上下滑动查看原代码),其中箭头表示【当前准备执行但还未执行的开始位置】。再次按下ctrl x a会退出该窗口模式。
设置断点也可以直接b 接对应的代码行数
比如main函数在第47行,b main 等价b 47
🌼2. 打印输出指定地址的值
这里适用于已知结构体+地址。
比如说结构体TreeNode,地址为0x555555559300。
打印每次都需要p root->xxxx...,如果树的深度太深则每次都需要从根节点root开始寻址太麻烦。
这里当我们已经知道了节点的地址后
打印指定地址0x555555559300的值和左右节点的值【这里是第三层】
p *((TreeNode*)0x555555559300)
打印其左右节点的值
p *((TreeNode*)0x555555559300)->left p *((TreeNode*)0x555555559300)->right
上面会显示当前的data值和左右指针的地址【即树TreeNode结构体的各个变量值】。
🌼3. 查看当前执行到哪行代码+代码内容
3.1 方式一:info line 结合 list 。
具体详情:
info line 获取当前执行代码的行号信息。
info line
info line 与 i line 等价
- 第53行代码的起始地址是
0x5555555553b5【
main
函数的偏移量为 41 的位置】。结束地址是0x5555555553c1【
main
函数的偏移量为 53 的位置】。即tree3_01.c
文件中第 53 行代码在程序运行时的地址范围,从main
函数的偏移量为 41 的位置开始,到main
函数的偏移量为 53 的位置结束。- 当前程序执行到
tree3_01.c
文件中第 53 行代码【未执行】。
list 查看代码内容
list
list 与 l 等价
如果没有指定参数,list
命令默认会显示当前执行位置的附近源代码。也可以指定行号或者函数名作为参数,以显示特定位置的源代码。
list
: 显示当前执行位置周围的源代码。list function_name
: 显示名为function_name
的函数的源代码。list line_number
: 显示指定行号的源代码。
3.2 方式二:f
在过程中,f
命令的功能是帮助了解当前执行的代码所在的位置,特别是在调试过程中出现错误时,可以帮助确认错误发生的地点。
3.3 方式三:tui模式
按下ctrl x a会显示下图的窗口(可以上下滑动查看原代码),其中箭头表示【当前准备执行但还未执行的开始位置】。再次按下ctrl x a会退出该窗口模式。
🌼4. 查看断点信息
info b
info b 与 i b等价
🌼5. 退出函数
前面我们知道进入函数单步执行用到的gdb指令是 s
退出函数用到的gdb指令是 finish
finish
finish 不与 f等价
finish功能是退出函数
f功能是查看当前执行的位置