GDB 常用调试技巧

1. 调试宏

宏是预编译的,无法 print 宏的定义。但是如果配合 gcc, 我们还是可以有限地调试宏。
在 GCC 编译程序的时候,加上 -g3 参数,就可以调试宏了。

  • info macro mac_name 可查看宏定义,及位置

  • macro expand mac_expr 可查看宏展开的样子

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;

#define MY_ADD(a,b) (a * 2 + b)
#define M 42
#define DM(x) (M+x)

int main(){
int s = MY_ADD(2,3);
cout<<s<<endl;
cout<<DM(s)<<endl;
return 0;
}

调试现场如下:

1
2
3
4
5
(gdb) i macro M
Defined at /home/zr/code/use_gdb/src3/./test_macro.cpp:5
#define M 42
(gdb) macro expand DM(1)
expands to: (42+1)

2. 修改变量

两种方法:

  1. print var_name=x

  2. set var var_name=x

示例:

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;

int main(){
int a = 0;
cout<<a+10<<endl;
cout<<a+10<<endl;
return 0;
}

调试现场如下:

1
2
3
4
5
6
7
8
9
(gdb) print a=42
$1 = 42
(gdb) n
52
7 cout<<a+10<<endl;
(gdb) set var a=1
(gdb) n
11
8 return 0;

3. 强制函数返回

使用

  • return

  • return expr
    来忽略还没有执行的语句并返回

4. 跳转执行

jump location 简写 j location 可以实现跳转调试。
location 可以是行号, +/-偏移, 文件名:行号, 函数名,*内存地址 等
使用 jump 需要小心:

  1. 它类似于 c 语言的 goto, 需要注意跳转前后的联系, 否则可能出现程序崩溃等问题

  2. jump 在跳转后会立即执行,如果要在跳转后高度,需要配合断点使用。