关于调试
程序遇到bug时候除了可以查看报错信息,跟踪Log,也可以通过调试的手段去解决。使用IDE时我们可以轻而易举的打断点调试,但是一旦脱离IDE,GDB就是一款强大的调式工具。
GDB 调试
What is GDB?
https://www.gnu.org/software/gdb/
GDB, the GNU Project debugger, allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed.
使用GDB
调试编译时,关掉编译器的优化选项(
-O
), 并打开调试选项(-g
)。另外,-Wall
选项打开所有警告信息。
arvin@VM-0-2-ubuntu:~/gdb$ g++ helloGDB.cpp print.cpp -g -Wall -o helloGDB
arvin@VM-0-2-ubuntu:~/gdb$ ls
helloGDB helloGDB.cpp print.cpp print.h
gdb常用调试命令
启动和退出
启动 gdb helloGDB
关闭 quit
查看代码
- 当前文件
list 等于 l
(gdb) list
1 #include"print.h"
2 #include
3 using namespace std;
4
5
6 int main()
7 {
8 cout << "Hello GDB\n";
9 cout << "What is GDB?\n";
10 cout << "The GNU Project Debugger\n";
从指定行显示 l 行号
l 14
(gdb) l 14
9 cout << "What is GDB?\n";
10 cout << "The GNU Project Debugger\n";
11 cout << "Hello GDB\n";
12 cout << "What is GDB?\n";
13 cout << "The GNU Project Debugger\n";
14 cout << "Hello GDB\n";
15 cout << "What is GDB?\n";
16 cout << "The GNU Project Debugger\n";
17 printNumber(10);
18 cout << "The GNU Project Debugger\n";
从指定函数显示 l 函数名
l printNumber
(gdb) l printNumber
1 #include "print.h"
2
3 void printNumber(int size)
4 {
5 for (int i = 0; i < size; ++i) {
6 cout << "The number is " << i << endl;
7 }
8 }
9
- 非当前文件
l 文件名:行号
l print.cpp:2
(gdb) l print.cpp:2
1 #include "print.h"
2
3 void printNumber(int size)
4 {
5 for (int i = 0; i < size; ++i) {
6 cout << "The number is " << i << endl;
7 }
8 }
9
l 文件名:函数名
l print.cpp:printNumber
(gdb) l print.cpp:printNumber
1 #include "print.h"
2
3 void printNumber(int size)
4 {
5 for (int i = 0; i < size; ++i) {
6 cout << "The number is " << i << endl;
7 }
8 }
9
- 设置显示的行数
查看默认显示的行数 list 等于 listsize
show list / show listsize
(gdb) show list
Number of source lines gdb will list by default is 10.
(gdb) show listsize
Number of source lines gdb will list by default is 10.
更改显示的函数
set list 13 / set listsize 14
(gdb) set list 13
(gdb) show list
Number of source lines gdb will list by default is 13.
(gdb) set listsize 14
(gdb) show listsize
Number of source lines gdb will list by default is 14.
- 断点操作
设置断点 b等于break
在当前文件设置断点
b 行号
(gdb) b 8
Breakpoint 1 at 0x92e: file helloGDB.cpp, line 8.
(gdb) break 10
Breakpoint 2 at 0x954: file helloGDB.cpp, line 10.
b 函数名
(gdb) break main
Note: breakpoint 1 also set at pc 0x92e.
Breakpoint 3 at 0x92e: file helloGDB.cpp, line 8.
在非当前文件设置断点
b 文件名:行号
(gdb) b print.cpp:4
Breakpoint 4 at 0xaeb: file print.cpp, line 4.
b 文件名:函数名
(gdb) b print.cpp:printNumber
Note: breakpoint 4 also set at pc 0xaeb.
Breakpoint 5 at 0xaeb: file print.cpp, line 5.
- 查看断点
i 等于 info
i b
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000092e in main() at helloGDB.cpp:8
2 breakpoint keep y 0x0000000000000954 in main() at helloGDB.cpp:10
3 breakpoint keep y 0x000000000000092e in main() at helloGDB.cpp:8
4 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:4
5 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
- 删除断点
d 等于 del 、delete
d 断点编号
(gdb) d 1
(gdb) d 2
(gdb) d 3
(gdb) i b
Num Type Disp Enb Address What
4 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:4
5 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
- 设置断点无效
dis 等于 disable
dis 断点编号
(gdb) dis 4
(gdb) i b
Num Type Disp Enb Address What
4 breakpoint keep n 0x0000000000000aeb in printNumber(int) at print.cpp:4
5 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
- 设置无效断点生效
ena 等于enable
(gdb) ena 4
(gdb) i b
Num Type Disp Enb Address What
4 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:4
5 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
- 设置条件断点
b 行号 if 变量==某个值
(gdb) b print.cpp:5 if i == 6
Note: breakpoints 4 and 5 also set at pc 0xaeb.
Breakpoint 6 at 0xaeb: file print.cpp, line 5.
(gdb) i b
Num Type Disp Enb Address What
4 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:4
5 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
6 breakpoint keep y 0x0000000000000aeb in printNumber(int) at print.cpp:5
stop only if i == 6
- 调试命令
start 只运一行
(gdb) start
Temporary breakpoint 7 at 0x92e: file helloGDB.cpp, line 8.
Starting program: /home/arvin/gdb/helloGDB
Temporary breakpoint 7, main () at helloGDB.cpp:8
8 cout << "Hello GDB\n";
run 一直运行到断点处停下
(gdb) b 10
Breakpoint 1 at 0x954: file helloGDB.cpp, line 10.
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000000954 in main() at helloGDB.cpp:10
(gdb) run
Starting program: /home/arvin/gdb/helloGDB
Hello GDB
What is GDB?
Breakpoint 1, main () at helloGDB.cpp:10
10 cout << "The GNU Project Debugger\n";
从断点的位置继续运行到下一个断点的位置
c 等于continue
(gdb) b 14
Breakpoint 2 at 0x5555555549a0: file helloGDB.cpp, line 14.
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000555555554954 in main() at helloGDB.cpp:10
breakpoint already hit 1 time
2 breakpoint keep y 0x00005555555549a0 in main() at helloGDB.cpp:14
(gdb) c
Continuing.
The GNU Project Debugger
Hello GDB
What is GDB?
The GNU Project Debugger
Breakpoint 2, main () at helloGDB.cpp:14
14 cout << "Hello GDB\n";
- 打印变量
p 等于print
print 变量名
Breakpoint 1, printNumber (size=10) at print.cpp:5
5 for (int i = 0; i < size; ++i) {
(gdb) print i
$1 = 0
- 打印变量类型
ptype 变量名
Breakpoint 1, printNumber (size=10) at print.cpp:5
5 for (int i = 0; i < size; ++i) {
(gdb) ptype i
type = int
- 单步调试
进入函数
s 等于 step 向下执行一行, 遇到函数, 进入函数
(gdb) step
The GNU Project Debugger
17 printNumber(10);
(gdb) step
printNumber (size=10) at print.cpp:5
5 for (int i = 0; i < size; ++i) {
不进入函数
n 等于 next 向下执行一行, 遇到函数, 不进入函数
Breakpoint 1, main () at helloGDB.cpp:16
16 cout << "The GNU Project Debugger\n";
(gdb) n
The GNU Project Debugger
17 printNumber(10);
(gdb) n
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9
18 cout << "The GNU Project Debugger\n";
跳出函数
要跳出的函数中不能有断点, 如果有要删除或者设置为无效的断点
finish
Breakpoint 1, main () at helloGDB.cpp:16
16 cout << "The GNU Project Debugger\n";
(gdb) step
The GNU Project Debugger
17 printNumber(10);
(gdb) step
printNumber (size=10) at print.cpp:5
5 for (int i = 0; i < size; ++i) {
(gdb) step
6 cout << "The number is " << i << endl;
(gdb) finish
Run till exit from #0 printNumber (size=10) at print.cpp:6
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9
main () at helloGDB.cpp:18
18 cout << "The GNU Project Debugger\n";
(gdb) n
The GNU Project Debugger
19 cout << "Hello GDB\n";
- 变量自动显示
自动打印指定变量的值
(gdb) display i
1: i = 0
查看自动打印哪些变量的值
i 等于 info
(gdb) i display
Auto-display expressions now in effect:
Num Enb Expression
1: y i
(gdb) n
6 cout << "The number is " << i << endl;
1: i = 0
(gdb) n
The number is 0
5 for (int i = 0; i < size; ++i) {
1: i = 0
取消自动打印
undisplay 编号
(gdb) undisplay 1
(gdb) n
6 cout << "The number is " << i << endl;
- 设置变量等于某一个值
set var 变量名=变量值
(gdb) step
The number is 1
5 for (int i = 0; i < size; ++i) {
(gdb) set var i = 8
(gdb) n
6 cout << "The number is " << i << endl;
(gdb) n
The number is 9
5 for (int i = 0; i < size; ++i) {
- 跳出循环
要跳出的循环代码块中不能有断点, 如果有要删除或者设置为无效的断点
until
The number is 2
5 for (int i = 0; i < size; ++i) {
(gdb) until
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9
8 }
有断点时:
(gdb) until
The number is 1
5 for (int i = 0; i < size; ++i) {
VSCode 真香