1.GDB 的基本介绍
GDB, 是 The GNU Project Debugger
的缩写, 是 Linux 下功能全面的调试工具。GDB 支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调试手段。在 Linux 环境软件开发中,GDB 是主要的调试工具,用来调试 C 和 C++ 程序。
在终端输入以下命令安装 GDB:
1 | sudo apt-get install gdb |
1.GDB的进入和退出
首先用bugging.c作为实验例子。
1 |
|
如果要调试程序,需要在 gcc 编译可执行程序时加上 -g
参数,首先我们编译 bugging.c
程序,生成可执行文件:
1 | gcc bugging.c -o bugging -g -m64 |
其中 -o
指定输出文件名, 虚拟机的环境是 64 位的操作系统,所以默认会编译为 64 位的程序,添加 -m64 选项可以编译为 64 位。
如果在你的环境里编译报错,请安装 libc6-dev-i386
后再次编译:
1 | sudo apt-get install libc6-dev-i386 |
输入 gdb bugging
进入 gdb 调试 bugging 程序的界面:
1 | gdb bugging |
在 gdb 命令行界面,输入run
执行待调试程序:
1 | (gdb) run |
在 gdb 命令行界面,输入quit
退出 gdb:
1 | (gdb) quit |
2.GDB 命令行界面使用技巧
命令补全:
任何时候都可以使用
TAB
进行补全,如果只有一个待选选项则直接补全;否则会列出可选选项,继续键入命令,同时结合TAB
即可快速输入命令。
部分 gdb 常用命令一览表:
命令 | 简写形式 | 说明 |
---|---|---|
list | l | 查看源码 |
backtrace | bt,where | 打印函数栈信息 |
next | n | 执行下一行 |
step | s | 一次执行一行,遇到函数会进入 |
finish | 运行到函数结束 | |
continue | c | 继续运行 |
break | b | 设置断点 |
info breakpoints | 显示断点信息 | |
delete | d | 删除断点 |
p | 打印表达式的值 | |
run | r | 启动程序 |
until | u | 执行到指定行 |
info | i | 显示信息 |
help | h | 帮助信息 |
查询用法:
在 gdb 命令行界面,输入
help command
可以查看命令的用法,command 是你想要查询的命令。
执行 Shell 命令:
在 gdb 命令行界面可以执行外部的 Shell 命令:
1
2 $ (gdb)!shell 命令
>
例如查看当前目录的文件:
3.GDB 查看源码
list 命令用来显示源文件中的代码。
- list 行号,显示某一行附近的代码:
- list 函数名,显示某个函数附近的代码:
- list 文件名 : 函数名,显示某一个文件某个函数附近的代码,用于多个源文件的情况。
4.GDB 断点
1.设置断点
break
命令用来设置断点。
- break 行号,断点设置在该行开始处,注意:该行代码未被执行:
- break 文件名 : 行号,适用于有多个源文件的情况。
- break 函数名,断点设置在该函数的开始处,断点所在行未被执行:
- break 文件名 : 函数名,适用于有多个源文件的情况。
2.查看断点信息
info breakpoints
命令用于显示当前断点信息。
其中每一项的信息:
- Num 列代表断点编号,该编号可以作为 delete/enable/disable 等控制断点命令的参数
- Type 列代表断点类型,一般为 breakpoint
- Disp 列代表断点被命中后,该断点保留(keep)、删除(del)还是关闭(dis)
- Enb 列代表该断点是 enable(y) 还是 disable(n)
- Address 列代表该断点处虚拟内存的地址
- What 列代表该断点在源文件中的信息
3.删除断点
delete
命令用于删除断点。
- delete Num,删除指定断点,断点编号可通过 info breakpoints 获得:
- delete,不带任何参数,默认删除所有断点:
4.关闭和启用断点
disable
命令和 enable
命令分别用于关闭和启用断点:
disable 命令用于关闭断点,有些断点可能暂时不需要但又不想删除,便可以 disable 该断点。
enable 命令用于启用断点。
- disable Num,关闭指定断点,断点编号可通过 info breakpoints 获得:
disable,不带任何参数,默认关闭所有断点。
enable Num,启用指定断点,断点编号可通过 info breakpoints 获得。
- enable,不带任何参数,默认启用所有断点。
disable 和 enable 命令影响的是 info breakpoints 的 Enb 列,表示该断点是启用还是关闭
5.断点启用的更多方式
enable
命令还可以用来设置断点被执行的次数,比如当断点设在循环中的时候,某断点可能多次被命中。
- enable once Num,断点 hit 一次之后关闭该断点
- enable delete Num,断点 hit 一次之后删除该断点
这两个命令影响的是 info breakpoints 的 Disp 列,表示该断点被命中之后的行为。
6. 断点调试的一些命令
- 打印变量
调试的过程中需要观察变量或者表达式的值,所以先介绍两个基本的显示变量值的命令:
info locals
打印当前断点处所在函数的所有局部变量的值,不包括函数参数。
print 变量或表达式
打印表达式的值,可显示当前函数的变量的值、全局变量的值等
print/FMT
可以控制打印的格式,常见的有x(十六进制)、t(二进制)、c(显示为字符)等。
- 启动程序
run 命令用于启动待调试程序,并运行到断点处停下。
run
不带任何参数,启动待调试程序,不传递参数。
run 参数
有些程序需要跟参数,直接带上参数列表即可,会传递给 main 函数的 argc、argv 变量。
- 单步命令
next, step, finish, continue, until 用于控制整个调试过程中,程序执行的流程。
next
next 单步执行,函数调用当做一条指令,不会进入被调用函数内部
next N,表示单步执行N次
step
step 单步执行,会进入到函数调用内部
step N,表示单步执行N次
finish
执行程序到当前函数结束
continue
执行程序到下个断点
until
until N,执行程序到源代码的某一行
7. 断点小结
断点是调试最基本的方法之一,这一节主要介绍了断点相关的知识。主要是几个断点相关的命令。
list
info breakpoints
break
delete
disable
和enable
enable once
和enable delete
next
,step
,finish
,continue
,until
info locals
和
不熟悉命令的时候,记得在 gdb 命令行下键入 help info breakpoints
等命令,查询帮助文档。