GDB调试 发表于 2023-06-30 | 更新于 2023-06-30
| 字数总计: 1.4k | 阅读时长: 5分钟 | 阅读量:
源程序 #include <iostream> using namespace std;#define NUM 10 int main (int argc, char * argv[]) { cout<<"参数个数:" <<argc<<endl; for (int i=0 ; i<argc; i++) { cout<<"参数 " <<i<<": " <<argv[i]<<endl; } cout<<"宏变量 " <<NUM<<endl; return 0 ; }
gdb调试准备 要进行调试首先要生成带调试信息的可执行文件,命令为g++ -g app.cpp -o app_g
。通过列表查看带调试信息的可执行文件大小比较大。
gdb启动和退出 注意gdb启动时,程序并没有运行
gdb app_g
启动GDB命令行界面
# 退出gdb # quit == q (gdb) quit
gdb传参 # 设置参数 (gdb) set args 1 2 3 # 显示参数 (gdb) show args
启动程序 # 执行到main的第一行阻塞 (gdb) start # 执行到断点位置或者将程序运行完 (gdb) run # 将暂停的程序继续运行,直到遇到一个断点或者程序结束 (gdb) continue
使用list查看文件中的代码 默认情况下list
查看到代码信息位于程序入口函数main
对应的那个文件中,因此如果不进行文件切换main
函数所在的文件就是当前文件 ,如果进行了文件切换,切换到哪个文件就是当前文件 。
查看代码 # 默认显示10行 (gdb) list # 查看更多内容 (gdb) 回车
切换文件 # 切换到指定文件,并查看指定行号的上下文,默认显示10行 (gdb) list 文件名:行号 # 切换到指定文件,并查看指定函数的上下文,默认显示10行 (gdb) list 文件名:函数名
设置显示的行数 # 以下两个命令中的listsize都可以写成list (gdb) set listsize 行数 # 查看当前list一次显示的函数 (gdb) show listsize
设置和查看断点 设置普通断点 # 在当前文件的某一行上设置断点 # break == b(gdb) b 行号 # 停在函数的第一行 (gdb) b 函数名
设置条件断点 # 必须要满足某个条件,程序才会停在这个断点的位置上 # 通常在循环中使用条件断点 (gdb) b 行号 变量名==某个值
查看断点 # info == i # 查看设置的断点信息 # info break (gdb) i b
删除断点 # delete == del == d # 需要 info b 查看断点的信息,第一列就是编号 (gdb) d 断点的编号 # 举例 # 删除第1个断点 (gdb) d 1 # 删除第2,4,6个断点 (gdb) d 2 4 6 # 删除范围内的断点 # 删除第1个到第5个断点 (gdb) d 1-5
设置断点状态 设置断点无效 # disable == dis# 设置某一个或者几个断点无效 (gdb) dis 断点1的编号 [断点2的编号 ...] # 设置某一个区间断点无效 (gdb) dis 断点1编号-断点n编号
让无效的断点生效 # enable == ena# 设置某一个或者几个断点无效 (gdb) ena 断点1的编号 [断点2的编号 ...] # 设置某一个区间断点无效 (gdb) ena 断点1编号-断点n编号
打印变量和变量类型
格式化字符(/fmt)
说明
/x
十六进制
/d
有符号,十进制
/u
无符号、十进制
/o
八进制
/t
二进制
/f
浮点数
/c
字符型
打印变量名 # print == p# 以十进制格式 (gdb) p 变量名 # 以十六进制格式 (gdb) p/x 变量名 # 以八进制格式 (gdb) p/o 变量名
打印变量类型
跟踪变量 display
命令可以跟踪变量
或者表达式
的值,每单程序暂停执行(例如单步执行时),GDB调试器就会自动帮我们打印出来。
设置变量自动显示 # 在变量的有效取值范内, 自动打印变量的值(设置一次, 以后就会自动显示) (gdb) display 变量名 # 以指定的整形格式打印变量的值, 关于 fmt 的取值, 请参考 print 命令 (gdb) display/fmt 变量名
查看自动显示列表 # info == i (gdb) info display
取消自动显示(删除) # 命令中的 num 是通过 info display 得到的编号, 编号可以是一个或者多个 (gdb) undisplay num [num1 ...] # num1 - numN 表示一个范围 (gdb) undisplay num1-numN (gdb) delete display num [num1 ...] (gdb) delete display num1-numN
取消自动显示(禁用) # 命令中的 num 是通过 info display 得到的编号, 编号可以是一个或者多个 (gdb) disable display num [num1 ...] # num1 - numN 表示一个范围 (gdb) disable display num1-numN
启用被禁用的变量 # 命令中的 num 是通过 info display 得到的编号, 编号可以是一个或者多个 (gdb) enable display num [num1 ...] # num1 - numN 表示一个范围 (gdb) enable display num1-numN
单步调试 # step若当前行是函数,进入函数内部 step == s # 若通过step进入到函数内部,想要跳出函数体,可以执行finish (gdb) finish # next不会进入函数内部 next == n
注意
:若函数内部有断点,使用finish
无法跳出函数,会执行到断点的位置。所以说finish
和continue
在程度上有很相似的作用。
使用until跳出循环体 生效条件:
循环体内不能有有效的断点,否者无法跳出循环体
必须在循环体的开始/结束执行该命令
设置变量值 # 可以在循环中使用, 直接设置循环因子的值 # 假设某个变量的值在程序中==90的概率是5%, 这时候可以直接通过命令将这个变量值设置为90 (gdb) set var 变量名=值