Linux下的GDB(GNU Debugger)是功能强大的调试工具,主要用于C/C++等程序的调试,支持断点设置、变量查看、内存分析、堆栈跟踪等功能,掌握GDB的使用能显著提升程序开发效率和问题排查能力,以下从安装、基础操作到进阶技巧详细说明其使用方法。
安装GDB
在Linux系统中,GDB通常可通过包管理器安装,不同发行版的命令略有差异:
- Ubuntu/Debian:
sudo apt update && sudo apt install gdb
- CentOS/RHEL:
sudo yum install gdb
(需启用EPEL源) - Fedora:
sudo dnf install gdb
安装完成后,通过gdb --version
确认版本,如GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
。
调试流程:从编译到运行
GDB调试的前提是程序包含调试符号(即源代码与可执行文件的关联信息),因此编译时需添加-g
选项,以C语言为例:
编译程序
gcc -g -o test_program test_program.c # -g保留调试信息,-o指定输出文件
若涉及多文件,需为每个源文件添加-g
,如gcc -g main.c utils.c -o app
。
启动GDB
gdb ./test_program # 调试指定可执行文件
启动后进入GDB交互界面,提示符为(gdb)
,也可直接运行gdb
再通过file
命令加载程序:
(gdb) file ./test_program
核心调试操作
设置断点
断点是暂停程序执行的关键位置,支持多种设置方式:
- 行号断点:在指定行暂停,如
break 10
(第10行)。 - 函数断点:在函数入口暂停,如
break main
(main函数)。 - 条件断点:满足条件时触发,如
break 15 if x > 10
(第15行且x>10)。 - 临时断点:触发后自动删除,如
tbreak 20
。
查看断点:info breakpoints
(或info b
),可看到断点编号、位置、条件等。
运行与控制程序
run
(或r
):启动程序,若需传入参数,可用run arg1 arg2
。continue
(或c
):从当前断点继续执行,直到下一个断点或程序结束。next
(或n
):单步执行,但不进入函数内部(逐过程执行)。step
(或s
):单步执行,若遇到函数则进入函数内部(逐语句执行)。finish
:执行到当前函数返回,并显示返回值。quit
(或q
):退出GDB,程序若未结束会提示确认。
查看变量与内存
print
(或p
):打印变量值,支持格式化输出,如:(gdb) p x # 打印变量x (gdb) p/x x # 以十六进制打印x (gdb) p *ptr # 解引用指针ptr (gdb) p arr[0:3] # 打印数组arr的前3个元素
display
:持续显示变量值,每次程序暂停时自动更新,如display i
。undisplay
:取消持续显示,需指定编号(通过info display
查看)。x
:检查内存内容,格式为x/格式 地址
,如:(gdb) x/4wx 0x00400000 # 以4字宽度、十六进制打印地址0x00400000开始的内存
堆栈与线程分析
backtrace
(或bt
):查看函数调用堆栈,显示当前执行路径,如:(gdb) bt #0 main (argc=1, argv=0x7fffffffe578) at test_program.c:10 #1 __libc_start_main (main=0x4011a6, argc=1, argv=0x7fffffffe578, init=0x4013b0, fini=0x4013d0, rtld_fini=0x7ffff7fc5b60, stack_end=0x7fffffffe468) at ../csu/libc-start.c:308
frame
(或f
):切换堆栈帧,如frame 1
(切换到第1层调用栈),可查看对应帧的变量。info threads
:查看多线程列表,线程编号前表示当前线程。thread 线程编号
:切换调试的线程,如thread 2
。
常用命令速查表
命令缩写 | 完整命令 | 功能说明 | 示例 |
---|---|---|---|
b | break | 设置断点 | b 15, b main, b 10 if x>0 |
r | run | 启动程序 | r arg1 arg2 |
c | continue | 继续执行至下个断点 | c |
n | next | 单步执行(不进入函数) | n |
s | step | 单步执行(进入函数) | s |
p | 打印变量/表达式值 | p x, p/x 0x100 | |
bt | backtrace | 查看函数调用堆栈 | bt |
info b | info breakpoints | 查看断点信息 | info b |
d | delete | 删除断点 | d 1(删除断点1) |
q | quit | 退出GDB | q |
进阶技巧
调试core dump文件
程序崩溃时会产生core文件,可通过gdb 程序名 core文件名
分析崩溃原因:
gdb ./test_program core.12345 (gdb) bt # 查看崩溃时的堆栈
需确保系统允许生成core文件(ulimit -c unlimited
)。
调试动态链接库
若程序依赖动态库,需指定库路径:
(gdb) set solib-search-path /path/to/libs (gdb) run
修改变量值(调试时)
调试过程中可临时修改变量值以测试逻辑,如:
(gdb) p x = 10 # 将x赋值为10
调试注意事项
- 编译选项:务必使用
-g
编译,否则无法查看源码和变量。 - 优化选项:若使用
-O2
等优化选项,变量可能被编译器优化,导致调试信息不准确,建议调试时用-O0
(无优化)。 - 断点位置:断点需设置在可执行代码行(如非注释、非声明语句),否则可能报错。
FAQs
Q1:为什么GDB调试时提示“No symbol table in file”?
A:通常是因为编译时未添加-g
选项,导致程序缺少调试符号,重新编译程序:gcc -g -o program program.c
,再启动GDB即可。
Q2:如何调试多线程程序中的特定线程?
A:通过info threads
查看所有线程,使用thread 线程编号
切换目标线程,再结合break
设置线程断点(如break thread 3:10
,表示线程3的第10行断点),或用thread apply all command
对所有线程执行命令(如thread apply all p x
)。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/25564.html