Linux下gdb调试方法
GDB(GNU Debugger)是Linux环境下一款强大的命令行调试工具,由GNU项目提供,用于帮助开发者诊断和修复程序中的错误。它支持多种编程语言,包括C、C++、Fortran、Pascal以及其他使用GNU编译器集合(GCC)编译的语言。GDB提供了丰富的功能,如设置断点、单步执行代码、查看和修改变量值、查看调用堆栈、分析内存、执行程序直到特定条件满足等,这些都是软件开发和调试过程中不可或缺的工具。
如何使用GDB进行调试程序:
准备程序
-
编译程序时加入调试信息:使用
gcc
或g++
编译时,需要添加-g
选项,以便在可执行文件中包含调试信息。例如:gcc -g my_program.c -o my_program
启动GDB
-
启动GDB:在命令行中输入
gdb
后跟你的程序名来启动GDB并加载程序。gdb my_program
基本命令
-
运行程序:在GDB提示符下,输入
run
或r
来运行程序。(gdb) run
-
设置断点:可以使用
break
命令(简写为b
)在特定的函数名或代码行设置断点。(gdb) break main # 在main函数开始处设置断点 (gdb) break 42 # 在第42行设置断点
-
单步执行:使用
step
(简写为s
)命令逐行执行代码,进入函数内部;使用next
(简写为n
)命令跳过函数内部,直接执行到下一行。(gdb) step (gdb) next
-
查看变量值:使用
print
(简写为p
)命令查看变量或表达式的值。(gdb) print variable_name
-
继续执行至下一个断点:当程序在某个断点暂停时,使用
continue
(简写为c
)命令继续执行,直到遇到下一个断点。(gdb) continue
-
查看调用堆栈:使用
backtrace
(简写为bt
)查看当前的函数调用堆栈。(gdb) backtrace
-
退出GDB:输入
quit
(简写为q
)退出GDB。(gdb) quit
进阶使用
- 条件断点:可以在设置断点时指定条件,例如,
break if condition
会在condition
为真的时候才触发断点。 - 查看内存和寄存器:使用
x
命令查看内存内容,info registers
查看CPU寄存器状态。 - 修改变量值:使用
set variable variable_name = value
命令修改变量值。 - 脚本和自动化:GDB支持编写脚本来自动化调试任务,可以使用
source
命令执行脚本文件。
GDB是一个功能丰富且高度可配置的工具,熟练掌握它对于提高程序调试效率至关重要。由于它是一个命令行工具,初学者可能需要一段时间来熟悉各种命令,但一旦掌握,会发现它在复杂调试场景中的强大和灵活性。
编译Debug版本程序
若要调试程序,编译程序的时候必须带上-g调试选项,让程序附带debug信息
$gcc -g xxx.c -o a.out
$g++ -g xxx.cpp -o a.out
启动调试程序
GDB启动参数 | 简写 | 解释 |
---|---|---|
-quiet | -q | 不打印GDB的介绍信息和版权信息 |
-symbols= | -s | 指定被调试程序的符号表文件 |
-exec= | -e | 指定被调试程序的名称 |
-se= | 读取符号表的文件和可执行文件 | |
-core= | -c | 使用文件作为一个coredump文件来测试 |
-directory= | -d | 指定被调试程序的源文件搜索路径。默认搜索路径是环境变量PATH |
-cd= | 指定工作目录,默认为当前目录 | |
--args | 若被调试程序后面携带参数,需要加上--args |
这里以调试a.out程序为例子(a.out 为附带debug信息的可执行程序)
启动调试程序
$gdb a.out
当不需要查看gdb版本信息时,可以使用-q参数取消打印gdb版本信息
$gdb -q a.out
当要调试的程序带有参数时,需要使用--args选项启动可执行程序,并且在可执行程序后边加上参数
$gdb --args a.out 100 200
常用调试命令
调试过程控制
命令 | 简写 | 解释 |
---|---|---|
(gdb) run | r | 运行程序,会自动在第一个断点处暂停执行 |
(gdb) start | 运行程序,单步执行,停在第一执行语句 | |
(gdb) next | n | 单步调试,直接执行不会进入函数,类似于Step Over |
(gdb) step | s | 单步调试,若遇到函数会进入内部,类似于Step Into |
(gdb) finish | fi | 单步调试,执行完函数并跳出函数,类似于Step Out |
(gdb) until <line_number> | u | 使程序运行至第line_number行处暂停,类似于Run To Cursor |
(gdb) continue | c | 继续运行,直至遇到断点或者程序结束 |
(gdb) quit | q | 终止调试 |
调试断点设置
调试断点命令 | 简写 | 解释 |
---|---|---|
(gdb) info break [n] | info b [n] | 显示当前程序的断点,其中n为可选的断点编号 |
(gdb) break <line_number> | b <line_number> | 添加断点,line_number为源代码的行号 |
(gdb) clear <line_number> | 删除断点,line_number为源代码的行号 | |
(gdb) delete | 删除断点,n为断点的编号 | |
(gdb) delete breakpoints | 删除所有断点 | |
(gdb) enable | 启用断点,n为断点的编号 | |
(gdb) disable | 暂停断点,n为断点的编号 |
调试源码查看
查看源码命令 | 简写 | 解释 |
---|---|---|
(gdb) list | l | 列出程序源码,默认每次显示10行 |
(gdb) list <line_number> | 列出程序源码,以line_number行为中心显示前后10行代码 | |
(gdb) list <func_name> | 将显示“func_name”函数的源代码 |
运行时信息查看
打印信息 | 简写 | 解释 |
---|---|---|
(gdb) print <表达式> | p | 输出表达式的值,“表达式”可以是任何数字、变量、函数调用等 |
(gdb) display <表达式> | 显示表达式的值,单步调试时每次执行都会输出显示 | |
(gdb) watch <表达式> | 设置监视点,当表达式的值发生变化会强行终止正在被调试的程序 | |
(gdb) whatis <表达式> | 查看表达式的类型定义 | |
(gdb) backtrace | bt | 显示当前调用堆栈 |
多线程调试方法
命令 | 解释 |
---|---|
(gdb) info threads | 查看当前进程的所有线程运行情况 |
(gdb) thread | 切换到具体id编号的线程上去 |
(gdb) thread apply | 让一个或者多个线程执行GDB命令CMD |
(gdb) thread apply all | 让所有被调试线程执行GDB命令CMD |
以下是多线程中断点的设置方法 | |
(gdb) break <line_number> thread | 在某个文件的line_number行添加断点,只作用于ID指定的线程 |
(gdb) break <line_number> thread all | 在某个文件的line_number行添加断点,作用于所有的线程 |
分割窗口设置
分割窗口 | 解释 |
---|---|
(gdb) layout src | 显示源代码窗口 |
(gdb) layout asm | 显示反汇编窗口 |
(gdb) layout regs | 显示源代码/反汇编和CPU寄存器窗口 |
(gdb) layout split | 显示源代码和反汇编窗口 |
Ctrl + L | 刷新窗口显示 |
Linux下常用的调试场景
在Linux下执行可执行程序时经常会打印Segmentation fault(段错误),当遇到这种情况时,我们可以通过查看程序执行时的堆栈信息定位程序出错的大体位置信息,以方便我们查找问题。
例如执行a.out 时,出现这种情况
$a.out 100 200
Segmentation fault
使用如下命令启动调试程序
$gdb -q --args a.out 100 200 #启动调试程序
(gdb)r #run 运行程序
... #这里会打印程序执行异常
(gdb)bt #backtrace 打印程序堆栈信息
··· #此时会打印程序的调用堆栈,通过查看堆栈可以得知在调用那个函数时发生崩溃你
(gdb)q #退出调试程序
- 点赞
- 收藏
- 关注作者
评论(0)