Linux下如何使用GDB调试程序?

在Linux系统中,GDB(GNU Debugger)是功能强大的调试工具,主要用于C/C++等程序的调试,支持断点设置、变量查看、内存分析、堆栈跟踪等功能,掌握GDB的使用能显著提升程序问题定位的效率,以下从安装、启动、基本操作到高级功能详细说明其使用方法。

linux下如何使用gdb调试

安装与启动GDB

安装GDB

不同Linux发行版的安装命令不同:

  • Ubuntu/Debiansudo apt update && sudo apt install gdb
  • CentOS/RHELsudo yum install gdbsudo dnf install gdb(较新版本)
    安装完成后,通过gdb --version验证是否成功,例如输出GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2表示安装成功。

启动GDB

启动GDB主要有三种方式:

  • 调试可执行文件gdb <程序名>,例如gdb ./a.out(需先编译生成可执行文件,编译时加-g选项保留调试信息,如gcc -g test.c -o test)。
  • 附加到运行中进程gdb -p <进程ID>,例如gdb -p 1234(适用于调试正在运行的程序,需配合ps aux查看进程ID)。
  • 分析core文件gdb <程序名> <core文件>,例如gdb ./test core.1234(程序崩溃时生成core文件,需通过ulimit -c unlimited开启core文件生成功能)。

基本调试流程

调试的核心是“设置断点→运行程序→暂停观察→分析问题→修复验证”,以下是关键操作:

设置断点

断点是程序暂停的位置,GDB支持多种断点类型:

  • 行断点:在指定代码行暂停,例如break 10(第10行)、b test.c:20(test.c文件第20行)。
  • 函数断点:在函数入口处暂停,例如break main(main函数)、b 'void func(int)'(带函数签名)。
  • 条件断点:满足条件时暂停,例如break 20 if i==5(第20行且变量i等于5时触发)。
  • 临时断点:触发后自动删除,例如tbreak 30(第30行,仅暂停一次)。
  • 硬件断点:基于CPU寄存器,适用于调试内存访问(如watch命令),数量有限但性能高。

查看断点列表:info breakpoints(可缩写为i b),删除断点:delete 1(删除编号1的断点)、clear 10(删除第10行的所有断点)。

linux下如何使用gdb调试

运行与控制程序

  • 运行程序run(可缩写为r),若需传参数,直接在命令后添加,例如r arg1 arg2
  • 继续执行continue(可缩写为c),从当前断点继续运行到下一个断点或程序结束。
  • 逐过程执行next(可缩写为n),执行下一行代码(若遇到函数调用,不进入函数内部)。
  • 逐语句执行step(可缩写为s),执行下一行代码(若遇到函数调用,进入函数内部)。
  • 执行到函数返回finish,运行到当前函数返回,并显示返回值和局部变量。
  • 跳转执行jump 15,跳转到第15行执行(需谨慎,可能破坏程序状态)。

查看变量与内存

  • 打印变量值print <变量名>(可缩写为p),例如p i打印变量i的值,支持格式化输出,如p/x i(十六进制)、p/c i(字符)、p/s str(字符串)。
  • 自动显示变量display <变量名>,每次程序暂停时自动显示该变量值,例如display i;取消自动显示:undisplay <编号>(通过info display查看编号)。
  • 监视变量变化watch <变量名>,当变量被修改时暂停,例如watch i;查看监视点:info watchpoints(可缩写为i watch)。
  • 查看内存x/<格式><数量><地址>,例如x/10xw &i(从变量i的地址开始,查看10个32位十六进制整数),格式说明:x(十六进制)、d(十进制)、f(浮点数)、c(字符)、s(字符串),单位:b(字节)、h(半字,2字节)、w(字,4字节)、g(双字,8字节)。

堆栈与线程分析

  • 查看调用栈backtrace(可缩写为bt),显示函数调用链,例如bt 0 3(显示0-3层栈帧),栈帧编号0表示当前函数。
  • 切换栈帧frame <编号>(可缩写为f <编号>),例如f 1切换到第1层栈帧,查看栈帧局部变量:info locals,查看函数参数:info args
  • 多线程调试info threads(可缩写为i th)列出所有线程,thread <编号>切换线程(如thread 2),设置线程断点:break main thread 3(仅在3号线程的main函数处暂停),锁定线程调度:set scheduler-locking on(防止调试时线程切换,聚焦当前线程)。

高级调试功能

调试多进程程序

默认情况下,GDB调试父进程,子进程由系统独立运行,可通过set follow-fork-mode child(调试子进程)或set follow-fork-mode parent(调试父进程)切换,

(gdb) set follow-fork-mode child  
(gdb) run  

此时GDB会附加到子进程进行调试。

调试动态库

程序使用动态库时,需加载调试符号:

  • 查看已加载的动态库:info sharedlibrary(可缩写为i sh)。
  • 指定动态库路径:set solib-search-path /path/to/libs(若动态库不在默认路径)。
  • 重新加载动态库符号:sharedlibrary <库名>,例如sharedlibrary libc.so.6

远程调试

通过GDB的远程调试功能,可在本地调试远程主机上的程序,需配合gdbserver:

  • 远程主机运行:gdbserver :1234 ./program(监听1234端口)。
  • 本地连接:target remote <远程IP>:1234,例如target remote 192.168.1.100:1234

GDB脚本与自动化

将调试命令写入脚本文件(如debug.cmd),通过source debug.cmd批量执行,

linux下如何使用gdb调试

break main  
run  
print argc  
next  
finish  
quit  

执行命令:gdb -x debug.cmd ./program

常用GDB命令速查表

命令(缩写) 功能描述 示例
break (b) 设置断点 b 10, b main, b test.c:20
info breakpoints (i b) 查看断点列表 i b
run (r) 运行程序 r arg1 arg2
continue (c) 继续执行 c
next (n) 逐过程执行(不进函数) n
step (s) 逐语句执行(进函数) s
finish 执行到当前函数返回 finish
print (p) 打印变量值 p i, p/x i
display 自动显示变量 display i
watch 监视变量变化 watch i
backtrace (bt) 查看调用栈 bt, bt 0 3
frame (f) 切换栈帧 f 1
info threads (i th) 查看线程列表 i th
thread 切换线程 thread 2
quit (q) 退出GDB q

相关问答FAQs

Q1: GDB调试时如何进入汇编代码查看底层逻辑?
A: 使用display/i $pc命令($pc是程序计数器),每次暂停时自动显示当前汇编指令;或直接使用stepi(可缩写为si)逐条汇编指令执行,nexti(可缩写为ni)逐条汇编指令执行但不进入函数调用。layout asm可进入汇编视图模式,layout regs显示寄存器状态,退出布局视图用layout off

Q2: GDB调试多线程程序时,如何定位特定线程的问题?
A: 首先通过info threads查看所有线程,重点关注状态为runningsleeping的线程,切换到目标线程:thread <线程ID>(如thread 3);设置线程断点:break <函数名> thread <线程ID>(如break func thread 3,仅3号线程进入func时暂停);为避免线程切换干扰,可锁定调度:set scheduler-locking on(调试完成后用set scheduler-locking off恢复),通过thread apply all <命令>可对所有线程执行命令,如thread apply all bt查看所有线程的调用栈。

原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/25560.html

(0)
酷番叔酷番叔
上一篇 2025年9月18日 18:45
下一篇 2025年9月18日 18:56

相关推荐

  • 如何强制停止Linux的tail监控?

    前台运行的tail(最常见情况)当tail命令直接在终端中执行时(占用当前终端):操作:按下组合键 Ctrl + C原理:Ctrl + C 会发送 SIGINT 信号,强制终止当前前台进程,示例:$ tail -f /var/log/syslog # 执行后持续输出日志^C # 按下Ctrl+C,tail立即终……

    2025年7月27日
    10100
  • Linux系统中如何正确卸载已安装的程序?

    Linux系统卸载程序的方法因安装方式和发行版的不同而有所差异,与Windows系统通过“控制面板”统一卸载不同,Linux依赖包管理器来管理软件,因此卸载时需根据程序最初安装的方式选择对应的工具,本文将详细介绍Linux系统中不同类型程序的卸载方法,包括基于APT、YUM/DNF、Pacman包管理器的发行版……

    2025年9月27日
    6500
  • linux 如何启动perf

    Linux中,启动perf可以使用命令sudo perf,或者指定

    2025年8月10日
    7400
  • linux编辑后如何保存退出

    Linux 中编辑后,通常按 Esc 键退出编辑模式,然后输入

    2025年8月17日
    11300
  • Linux中如何执行SQL脚本文件?

    在Linux环境下执行SQL脚本文件是数据库管理和开发中的常见操作,无论是初始化数据库结构、批量导入数据还是执行备份恢复,都离不开这一技能,整个过程需要明确数据库类型、脚本格式及执行权限,以下是具体操作方法和注意事项,执行前的准备工作确认数据库环境首先需要明确当前系统安装的数据库类型(如MySQL、Postgr……

    2025年9月25日
    8400

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN

关注微信