GDB——Linux下的调试工具
GDB安装
- 使用`yum
1yum install gdb -y
- 使用
scl
1scl enable devtoolset-9
使用GDB调试
使用GDB调试指定文件
- 生成支持
gdb
调试的二进制文件
1gcc -g -o main main.c #添加-g参数来支持gdb调试
2
3#更推荐使用下面的方式使用gdb
4gcc -Og -o main main.c #-O参数指定1-4级的优化级别,默认为1
- 使用
gdb
启动二进制文件
1gdb main
不指定文件调试GDB
直接执行命令gdb
使用file
指令指定当前要修改的文件
1gdb -q # -q means quiet,disable the notify info
2(gdb) file <target-file>
参数传递
- 启动时使用
--args
参数
1gdb --args main.exe [argfile-name]
2#例如使用args.file存储参数
3gdb --args main.exe args.file
gdb
启动后使用set args
指令设置参数存储文件
1(gdb) set args [argsfile-name]
- 在使用
gdb
的run
或start
指令时指定参数文件
1(gdb)run [argsfile-name]
2(gdb)start [argsfile-name]
结果输出
1(gdb)run > a.txt #将结果覆盖工作目录下的文件a.txt
常用GDB指令
指令 | 作用 |
---|---|
break ``b |
在指定第`` 处添加断点 |
run``r |
运行程序 |
continue``c |
执行到下一个断点或直接执行完毕如果是函数调用,则不会步入 |
next``n``next n |
执行当前位置的下一行代码如果是函数调用,则会步入next n 代表往下执行n 行 |
print ``p |
打印变量``的值 |
list``l |
打印程序源码 |
quit``q |
终止调试 |
cd |
变更gdb 的工作目录,gdb 工作目录是启动gdb 所在的目录,一般要保证gdb 的工作目录为源码目录 |
path |
在gdb 内部,append``到PATH 变量中 |
watch |
监控变量,只要变量发生变更。就停止运行注意,watch 也可以监控一个表达式是否发生变化 |
info watchpoints |
查看监控点数量 |
info break |
查看断点信息 |
GDB断点
GDB断点类型 | 对应指令 |
---|---|
普通断点 | break orb |
观察断点 | watch |
捕捉断点 | catch |
Break指令
location
参数的选取以及含义
location 的值 |
含义 |
---|---|
linenum |
linenum 是一个整数,表示要打断点处代码的行号。要知道,程序中各行代码都有对应的行号,可通过执行 l(小写的 L)命令看到。 |
filename:linenum |
filename 表示源程序文件名;linenum 为整数,表示具体行数。整体的意思是在指令文件 filename 中的第 linenum 行打断点。 |
|
| + offset
- offset
| offset
为整数(假设值为 2),+offset
表示以当前程序暂停位置(例如第 4 行)为准,向后数 offset 行处(第 6 行)打断点;-offset
表示以当前程序暂停位置为准,向前数offset
行处(第 2 行)打断点。
|
| function
| function
表示程序中包含的函数的函数名,即 break
命令会在该函数内部的开头位置打断点,程序会执行到该函数第一行代码处暂停。
|
| filename:function
| filename
表示远程文件名;function
表示程序中函数的函数名。整体的意思是在指定文件 filename
中 function
函数的开头位置打断点。 |
tbreak
t means temp.Tbreak
指令创建的断点在当前这次运行之后就会被删除
rbreak
r means rugular expression.rbreak
会在函数的开头打断点,使用正则表达式匹配函数名,所有匹配的函数都会被打上断点
1(gdb)rbreak <regular-expression>
条件断点
可以使用如下语句在特定条件下打断点break ... if <condition>
当<condition>
成立时,进行断点的设置
Watch指令
watch |
只有当被监控变量(表达式)的值发生改变,程序才会停止运行。 |
---|---|
rwatch |
只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行; |
awatch |
只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行。 |
注意事项
注意:如果一个变量还没有出现在上下文context
中(即程序还没运行到出现变量那一行),那就不能直接watch,一般直接在变量声明处打断点,然后再进行watch,示例如下
1(gdb) l
21 #include <iostream>
32 using namespace std;
43
54 int main(){
65
76 int a = 0;
87 while(a<=100){
98 a++;
109 }
1110
12(gdb) l
1311 return 0;
1412 }
15(gdb) watch a
16No symbol "a" in current context.
17(gdb) b 6
18Breakpoint 1 at 0x1171: file main.cpp, line 6.
19(gdb) run
20Starting program: /root/code/a.out
21
22Breakpoint 1, main () at main.cpp:6
236 int a = 0;
24(gdb) watch a
25Hardware watchpoint 2: a
条件断点
watch <expression> if <condition>
条件<condition>
成立时监控表达式或者变量<expression>
的值
Catch指令
catch指令是事件驱动
,即指定事件
(如异常)发生时,产生预定的动作
(打断程序)。
catch指令语法:catch <event>
event 取值 |
含义 |
---|---|
throw [exception] |
当程序中抛出 exception 指定类型异常时,程序停止执行。如果不指定异常类型(即省略 exception ),则表示只要程序发生异常,程序就停止执行。 |
catch [exception] |
当程序中捕获到exception 异常时,程序停止执行。exception 参数也可以省略,表示无论程序中捕获到哪种异常,程序都暂停执行。 |
load [regexp]``unload [regexp] |
其中,regexp 表示使用正则表达式 表示的目标动态库的名称,load 命令表示当 regexp 动态库加载时程序停止执行;unload 命令表示当 regexp 动态库被卸载时,程序暂停执行。regexp 参数也可以省略,此时只要程序中某一动态库被加载或卸载,程序就会暂停执行。 |
示例如下:
1(gdb) l
21 #include <iostream>
32 using namespace std;
43
54 int main(){
65
76 int a = 0;
87 while(a<=100){
98 a++;
109 }
1110 throw 100;
12(gdb) catch throw int
13Catchpoint 1 (throw)
14(gdb) run
15Starting program: /root/code/a.out
16
17Catchpoint 1 (exception thrown), 0x00007ffff7d82672 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
Condition指令
Condition指令给特定的断点添加条件表达式
增加condition语法:condition <bnum> <expression>
删除condition语法:condition <bnum>
<bnum>
为断点标号,可以使用info break
查看
只有当表达式成立时,特定断点才会生效,否则不进行中断
Ignore指令
ignore指定特定断点的失效次数
ignore语法:ignore <bnum> <count>
<bnum>
为断点标号,可以使用info break
查看<count>
为失效次数
失效次数每次-1,一旦一个断点的失效次数为0,那么断点生效
1(gdb) l
21 #include <iostream>
32 using namespace std;
43
54 int main(){
65
76 int a = 0;
87 while(a<=100){
98 a++;
109 }
1110 throw 100;
12(gdb) b 8
13Breakpoint 1 at 0x11c2: file main.cpp, line 8.
14(gdb) ignore 1 100 #跳过一号断点一百次
15Will ignore next 100 crossings of breakpoint 1.
16(gdb) run
17Starting program: /root/code/a.out
18
19Breakpoint 1, main () at main.cpp:8
208 a++;
21(gdb) print a
22$1 = 100 #在第一百一次循环的时候生效了,前一百次被跳过
23(gdb)
断点删除
普通断点info break [n]
查看断点信息,n为可选参数,标明查看某个断点的信息
观察断点info watchpoint [n]
- 删除指定位置所有断点
clear <location>
location 参数为某个函数的函数名时,表示删除位于该函数入口处的所有断点。
- 删除单个断点
delete <bnum>
<bnum>
为断点编号
断点禁用与激活
禁用断点可以暂时使断点失效。
- 禁用断点
disable [num...]
[num...]
表示多个断点编号,使用空格分割
- 激活断点
GDB单步调试
单步调试就是指每次指执行一行代码,有三个指令用来进行单步调试
指令名 | 效果 |
---|---|
next``next count |
跳过函数内部,直接按行执行不提供count 则默认count 为1 |
step``step count |
会进入函数内部 |
until``until location |
不带参数的until 命令,可以使 GDB 调试器快速运行完当前的循环体,并运行至循环体外停止,如果没在循环体中,那么也是执行下一行。location 表示,程序执行到某个位置时,进行停止。 |
1
标题:GDB——Linux下的调试工具
作者:cyberloafing
地址:https://www.goloaf.top/articles/2022/06/28/1656427040308.html
十三点