GDB 调试

来源:互联网 发布:淘宝店铺视频怎么拍的 编辑:程序博客网 时间:2024/06/05 07:51

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 sttype = 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 0x7fffffffe36c0x7fffffffe36c: 16

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

int val = 0x01020304

(gdb) p /a &val$1 = 0x7fffffffe37c(gdb) x /4db 0x7fffffffe37c0x7fffffffe37c: 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) cContinuing.Hardware watchpoint 2: valOld value = 0New value = 4main (argc=1, argv=0x7fffffffe468) at test.cpp:22

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

(gdb) break 17Breakpoint 1 at 0x400569: file test.cpp, line 17.(gdb) commands 1> watch val> c> end(gdb) rBreakpoint 1, main (argc=1, argv=0x7fffffffe468) at test.cpp:1717          int val = 1;Hardware watchpoint 2: valHardware watchpoint 2: valOld value = 0New 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:2525              *link_info = iter->second;(gdb) info argslink_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 result1: result = 0(gdb) n1: result = 0(gdb) n1: result = 0(gdb) n1: result = 1

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

0 0