GDB 调试

1. 调试命令

1.1 启动调试

【直接启动】 gdb prog
【启动加参】 gdb –args ./prog param
【启动加参】 ① gdb prog ② (gdb) run param

gdb a.out
(gdb) run 11 12 beijing

1.2 调试控制

r [run] 运行程序
c [continue] 断点后,继续运行
s [step] 执行一行代码,若为函数,则跳到函数内部
n [next] 执行一行代码,若为函数,则直接运行整个函数体
u [until] 结束循环
f [finish] 结束函数
where 任何时候查看代码执行在哪里

2. 查看

2.1 查看代码

l [list] 用于查看调试程序源代码。Note: 编译时,加参数-g。

  • (gdb) list 5, 查看第5行以后代码
  • (gdb) list ,20 查看 首行至20行
  • (gdb) list 10,20 查看10至20行
  • (gdb) list func 查看函数func代码
  • (gdb) list file.c:10 查看其它文件第10行代码
  • (gdb) list file.c:func 查看其它文件内函数

2.2 查看变量值

p [print] 用于查看变量

  • p i  打印变量i
  • p arr 打印静态数组
  • p arr@len  打印动态数组
  • p arr[4]@2 从arr[4] 向后打印两个
  • p *0x1234  打印地址内容

格式打印
p /FMT variable

FMT:
o octal  x hex  d decimal  u unsigned decimal  t binary  f float
a address  c char  s string

int arr1[] = {1, 2, 3, 4};
int *arr2 = new int[1];
*arr2 = 5;
int val = 16

(gdb) p arr1
$4 = {1, 2, 3, 4}
(gdb) p arr2[0]@1
$5 = {5}
(gdb) p /o val
$6 = 020

2.3 查看变量类型

pt [ptype] 查看变量类型,对于结构体,可以查看结构体内变量

struct Student
{
  int age;
  string name;
};

(gdb) pt st
type = struct Student {
int age;
std::string name;
}
(gdb) p st
$1 = {age = 20, name = "xiaoming"}

2.4 查看内存

x /FMT address

FMT 同1.2

(gdb) p /a &val
$1 = 0x7fffffffe36c
(gdb) x /d 0x7fffffffe36c
0x7fffffffe36c: 16

x /nfu address
n 显示组数
f FMT
u 几个字节组成一组 [b 单字节 h 双字节 w 四字节]

int val = 0x01020304

(gdb) p /a &val
$1 = 0x7fffffffe37c
(gdb) x /4db 0x7fffffffe37c
0x7fffffffe37c: 4       3       2       1

可见,该机器为小端,即低位字节放在低地址。如 04 放在 0x7fffffffe37c 。

3. 停止点

3.1 断点

b [break] 针对行号函数设置断点

  • (gdb) break function
  • (gdb) break class::function
  • (gdb) break class::function(type, type) 函数重载
  • (gdb) break linenum
  • (gdb) break filename:function
  • (gdb) break filename:linenum
  • (gdb) break *address

3.2 观察点

watch 针对变量有写操作时停住
rwatch 针对变量有读操作时停住
awatch 针对变量有读写操作时停住

[note] 观察点可以认为是针对变量设置断点。

15 int main(int argc, char *argv[])
16 {
17  int val = 1;
18
19  xxxxx
20
21  val = 4;
22 }

(gdb) break 17
(gdb) r
(gdb) watch val
(gdb) c
Continuing.
Hardware watchpoint 2: val

Old value = 0
New value = 4
main (argc=1, argv=0x7fffffffe468) at test.cpp:22

观察点检测变量,只能到变量的作用域中,才能添加观察点,非常不方便。这里,可以使用命令,自动添加观察点

(gdb) break 17
Breakpoint 1 at 0x400569: file test.cpp, line 17.
(gdb) commands 1
> watch val
> c
> end
(gdb) r
Breakpoint 1, main (argc=1, argv=0x7fffffffe468) at test.cpp:17
17          int val = 1;
Hardware watchpoint 2: val
Hardware watchpoint 2: val

Old value = 0
New value = 4

首先添加断点[ Breakpoint 1],然后添加命令,在断点1处执行。

3.3 查看停止点

info break   查看停止点
info break [n]   查看停止点N

info watchpoints 仅查看观察点

3.4 清除停止点

delete 清除全部
delete n 清除某个
delete m-n 清除范围
clear 清除范围内停止点

disable n 禁用某个停止点
enable n 启动某个停止点

disable m-n 禁用范围内停止点
enable m-n 启用范围内停止点

3.5 忽略断点N次

ignore n count

ignore 2 5 忽略5次断点2,即第6次时,停住。在循环时特别好用。

3.6 条件断点

break xxx if condition

int result = 0;
for (size_t i = 0; i < 100; i++)
{
 result += i;
}

(gdb) break 20 if result = 10

4. 堆栈

4.1 显示堆栈

bt [backtrace]

调试core的时候,一般是上来第一个命令,看程序挂在哪里。

4.2 切换堆栈

frame n  [切换栈帧]

4.3 查看堆栈信息

info frame 显示当前栈信息
info locals 显示当前栈局部变量
info args 显示函数实参

gdb a.out -c core.5117_a.out
(gdb) bt
#0 0x00007fcbd24124f3 in XXXX
#1 0x400ca5 in GetLinkInfo (link_id="19431", link_info=0x7ffff9dd9280) at main.cpp:25
#2 0x400dae in RemoveBadLink () at main.cpp:46
#3 0x400e4c in main () at main.cpp:60
(gdb) frame 1
#1  0x400ca5 in GetLinkInfo (link_id="19431", link_info=0x7ffff9dd9280) at main.cpp:25
25              *link_info = iter->second;
(gdb) info args
link_id = "19431"
link_info = 0x7ffff9dd9280

5. 调试进程

attach 上某个进程后,进程立即停止运行。在退出gdb,detach该进程后,进程才继续运行。

[方法一] gdb prog pid
[方法二] gdb prog -> (gdb) attach pid

6 其它

6.1 修改变量值

set var = 3    [仅修改]
print var = 3  [修改并打印]

10 int result = 0;
11 for (int i = 1; i < 100; i++)
12 {
13   result += i;
14 }

(gdb) set result = 200
(gdb) p result = 300
$1 = 300

6.2 自动显示

display var

(gdb) break 10
(gdb) r
(gdb) display result
1: result = 0
(gdb) n
1: result = 0
(gdb) n
1: result = 0
(gdb) n
1: result = 1

每执行一步,都会显示该变量,无论变量值是否发生变化。

要使用 GDB 调试程序,首先需要确保程序在编译时包含了调试信息。在使用 GCC 编译程序时,应添加 `-g` 选项,这样 GDB 才能读取源代码和变量信息,例如: ```bash gcc -g example.c -o example ``` 编译完成后,可以通过以下命令启动 GDB 并加载程序: ```bash gdb example ``` 如果程序已经编译完成,也可以先启动 GDB,然后再在 GDB 中加载程序: ```bash gdb (gdb) file example ``` 启动 GDB 后,可以使用 `run` 命令(简写为 `r`)来运行程序: ```gdb (gdb) run ``` 如果希望在启动程序时传递参数,可以在启动 GDB 时使用 `-args` 参数,或者在 GDB 中使用 `set args` 命令设置参数: ```bash gdb -args ./example arg1 arg2 ``` 或者在 GDB 中执行: ```gdb (gdb) set args arg1 arg2 ``` 如果需要调试一个正在运行的进程,可以使用 `attach` 命令,后面跟上进程的 PID: ```gdb (gdb) attach <pid> ``` 为了更有效地调试,可以使用断点来暂停程序的执行。使用 `break` 命令(简写为 `b`)来设置断点: ```gdb (gdb) break main ``` 这将在 `main` 函数处设置一个断点。当程序运行到断点时会暂停,此时可以检查变量的值、单步执行等。 单步执行可以使用 `step` 命令(简写为 `s`),它会进入函数内部执行: ```gdb (gdb) step ``` 如果不想进入函数内部,而是直接执行整个函数,可以使用 `next` 命令(简写为 `n`): ```gdb (gdb) next ``` 查看变量的值可以使用 `print` 命令(简写为 `p`): ```gdb (gdb) print variable_name ``` 查看当前执行的源代码可以使用 `list` 命令(简写为 `l`): ```gdb (gdb) list ``` 如果需要退出 GDB,可以使用 `quit` 命令(简写为 `q`): ```gdb (gdb) quit ``` 以上是使用 GDB 调试程序的基本步骤和常用命令[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值