源程序

#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 变量名

打印变量类型

ptype 变量名

跟踪变量

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无法跳出函数,会执行到断点的位置。所以说finishcontinue在程度上有很相似的作用。

使用until跳出循环体

生效条件:

  • 循环体内不能有有效的断点,否者无法跳出循环体

  • 必须在循环体的开始/结束执行该命令

设置变量值

# 可以在循环中使用, 直接设置循环因子的值
# 假设某个变量的值在程序中==90的概率是5%, 这时候可以直接通过命令将这个变量值设置为90
(gdb) set var 变量名=值