GDB

参考文章

1. 调试准备

-g 将调试信息写入到可执行程序中
gcc -g args.c -o app
项目程序如果是为了进行调试而编译时, 必须要打开调试选项(-g)。另外还有一些可选项:
在尽量不影响程序行为的情况下关掉编译器的优化选项(-O0),
-Wall选项打开所有 warning,
也可以发现许多问题,避免一些不必要的 bug。

2. 设置参数

gdb 可执行程序文件名
set args ...
show args
start 向下执行一行(从main开始)
c 继续
run/r 执行到断点或者执行完毕
q/quit 退出

3. 查看代码

3.1 当前文件

# 使用 list 和使用 l 都可以
# 从第一行开始显示
(gdb) list 

# 列值这行号对应的上下文代码, 默认情况下只显示10行内容
(gdb) list 行号

# 显示这个函数的上下文内容, 默认显示10行
(gdb) list 函数名

3.2 切换文件

# 切换到指定的文件,并列出这行号对应的上下文代码, 默认情况下只显示10行内容
(gdb) l 文件名:行号

# 切换到指定的文件,并显示这个函数的上下文内容, 默认显示10行
(gdb) l 文件名:函数名

3.3 设置显示的行数

# 以下两个命令中的 listsize 都可以写成 list
(gdb) set listsize 行数

# 查看当前list一次显示的行数
(gdb) show listsize

4. 断点操作

4.1 设置断点

# 设置普通断点到当前文件
# 在当前文件的某一行上设置断点
# break == b
(gdb) b 行号
(gdb) b 函数名        # 停止在函数的第一行

# 设置普通断点到某个非当前文件上
# 在非当前文件的某一行上设置断点
(gdb) b 文件名:行号
(gdb) b 文件名:函数名        # 停止在函数的第一行

# 设置条件断点
# 必须要满足某个条件, 程序才会停在这个断点的位置上
# 通常情况下, 在循环中条件断点用的比较多
(gdb) b 行数 if 变量名==某个值

4.2 查看断点

# info == i
# 查看设置的断点信息
(gdb) i b   #info break

# 举例
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400cb5 in main() at test.cpp:12
2       breakpoint     keep y   0x0000000000400cbd in main() at test.cpp:13
3       breakpoint     keep y   0x0000000000400cec in main() at test.cpp:18
4       breakpoint     keep y   0x00000000004009a5 in insertionSort(int*, int) 
                                                   at insert.cpp:8
5       breakpoint     keep y   0x0000000000400cdd in main() at test.cpp:16
6       breakpoint     keep y   0x00000000004009e5 in insertionSort(int*, int) 
                                                   at insert.cpp:16

在显示的断点信息中有一些属性需要在其他操作中被使用, 下面介绍一下:
Num: 断点的编号, 删除断点或者设置断点状态的时候都需要使用
Enb: 当前断点的状态, y表示断点可用, n表示断点不可用
What: 描述断点被设置在了哪个文件的哪一行或者哪个函数上

4.3 删除断点

# delete == del == d
# 需要 info b 查看断点的信息, 第一列就是编号
(gdb) d 断点的编号1 [断点编号2 ...]
# 举例: 
(gdb) d 1          # 删除第1个断点
(gdb) d 2 4 6      # 删除第2,4,6个断点

# 删除一个范围, 断点编号 num1 - numN 是一个连续区间
(gdb) d num1-numN
# 举例, 删除第1到第5个断点
(gdb) d 1-5

4.4 设置断点状态

# 设置断点无效
# 让断点失效之后, gdb调试过程中程序是不会停在这个位置的
# disable == dis
# 设置某一个或者某几个断点无效
(gdb) dis 断点1的编号 [断点2的编号 ...]

# 设置某个区间断点无效
(gdb) dis 断点1编号-断点n编号


# 让无效的断点生效
# enable == ena
# 设置某一个或者某几个断点有效
(gdb) ena 断点1的编号 [断点2的编号 ...]

# 设置某个区间断点有效
(gdb) ena 断点1编号-断点n编号

5. 调试命令

5.1 继续运行gdb

# continue == c
(gdb) continue

5.2 手动打印信息

5.2.1 打印变量值

格式化字符(fmt) 说明
%x 以十六进制的形式打印出整数。
%d 以有符号、十进制的形式打印出整数。
%u 以无符号、十进制的形式打印出整数。
%o 以八进制的形式打印出整数。
%t 以二进制的形式打印出整数。
%f 以浮点数的形式打印变量或表达式的值。
%c 以字符形式打印变量或表达式的值。
# print == p
(gdb) p 变量名

# 如果变量是一个整形, 默认对应的值是以10进制格式输出, 其他格式请参考上表
(gdb) p/fmt 变量名

# 举例
(gdb) p i       # 10进制
$5 = 3
(gdb) p/x i     # 16进制
$6 = 0x3
(gdb) p/o i     # 8进制
$7 = 03

5.2.2 打印变量类型

# 查看某个变量的类型
# 语法格式
(gdb) ptype 变量名

5.3 自动打印信息

5.3.1 设置变量名自动显示

# 每当程序暂停执行(例如单步执行)时,GDB 调试器都会自动帮我们打印出来
# 在变量的有效取值范围内, 自动打印变量的值(设置一次, 以后就会自动显示)
(gdb) display 变量名

# 以指定的整形格式打印变量的值, 关于 fmt 的取值, 请参考 print 命令
(gdb) display/fmt 变量名

5.3.2 查看自动显示列表

# info == i
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
1:   y  i
2:   y  array[i]
3:   y  /x array[i]

在展示出的信息中, 每个列的含义如下:
Num : 变量或表达式的编号,GDB 调试器为每个变量或表达式都分配有唯一的编号
Enb : 表示当前变量(表达式)是处于激活状态还是禁用状态,如果处于激活状态(用 y 表示),则每次程序停止执行,该变量的值都会被打印出来;反之,如果处于禁用状态(用 n 表示),则该变量(表达式)的值不会被打印。
Expression :被自动打印值的变量或表达式的名字。

5.3.3 取消自动显示

# 删除自动显示列表中的变量或表达式
# 命令中的 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) disable display num1-numN

5.4 单步调试

5.4.1 step

# 从当前代码行位置, 一次调试当前行下的每一行代码
# step == s
# 如果这一行是函数调用, 执行这个命令, 就可以进入到函数体的内部
(gdb) step

5.4.2 finish

# 如果通过 s 单步调试进入到函数内部, 想要跳出这个函数体,如果想要跳出函数体必须要保证函数体内不能有有效断点,否则无法跳出
(gdb) finish

5.4.3 next

# next == n
# 如果这一行是函数调用, 执行这个命令, 不会进入到函数体的内部
(gdb) next

5.4.4 until

通过 until 命令可以直接跳出某个循环体,这样就能提高调试效率了。如果想直接从循环体中跳出, 必须要满足以下的条件,否则命令不会生效:
要跳出的循环体内部不能有有效的断点
必须要在循环体的开始/结束行执行该命令
(gdb) until

5.5 设置变量值

# 可以在循环中使用, 直接设置循环因子的值
# 假设某个变量的值在程序中==90的概率是5%, 这时候可以直接通过命令将这个变量值设置为90
(gdb) set var 变量名=值
posted @ 2026-06-04 21:35  r5ett  阅读(16)  评论(0)    收藏  举报