当前位置: 首页 > backend >正文

嵌入式linux GDB使用教程

当然可以,以下是结合你所有需求(断点设置、程序启动、继续执行、寄存器查看、栈回溯、调试重启等)的:


✅ RK3588S 上 GDB 调试完整实战指南

适用于你当前的 dtof 程序调试。包含了从启动调试分析崩溃查看变量,再到重新运行的全流程。


🚀 一、准备工作

确保你编译时带上调试信息:

gcc -g -O0 -o dtof main.c ...

或确认 dtof 是带符号的可执行文件。


🧭 二、典型调试流程(推荐套路)

(gdb) file ./dtof                   # 加载可执行文件
(gdb) break main                   # 在 main 函数打断点
(gdb) break foo.c:42               # (可选) 在特定源码行打断点
(gdb) run                          # 开始运行程序,遇断点停下(gdb) print my_var                 # 打印变量
(gdb) info locals                  # 查看当前函数的局部变量
(gdb) info registers               # 查看所有寄存器(x0~x30, sp, pc 等)
(gdb) bt                           # 查看调用栈 backtrace
(gdb) frame 1                      # 切换到上一帧(查看调用路径)
(gdb) info locals                  # 查看该帧下局部变量(gdb) break main.c:88              # 再添加一个断点
(gdb) continue                     # 从当前停的位置继续执行
(gdb) next                         # 执行下一行,不进入函数
(gdb) step                         # 执行下一行,遇函数会进入
(gdb) finish                       # 跳出当前函数(gdb) info breakpoints             # 查看断点列表
(gdb) disable 2                    # 禁用编号为2的断点
(gdb) delete 2                     # 删除编号为2的断点(gdb) kill                         # 杀掉当前运行实例
(gdb) run                          # 从头重新执行
(gdb) quit                         # 退出 GDB

🧱 三、命令说明对照表

操作类别命令说明
打断点break main / break file:line在函数或源码行打断点
启动执行run从头运行程序
继续执行continuec从当前位置继续
单步执行next / step / finish分别用于逐行、进入函数、跳出函数
查看变量print x / info locals打印变量或所有局部变量
查看寄存器info registers / print $x0查看通用寄存器、栈指针、PC、LR
栈回溯backtracebt调用路径
切换调用帧frame n切换到指定调用帧
管理断点info breakpoints / delete查看、删除断点
重启程序kill + run杀掉当前实例再重启
退出调试quit退出 GDB

🧠 四、调试技巧提示

场景推荐命令
崩溃了(如段错误)btframe 0info locals 查看崩溃现场
想从头再跑一次killrun
程序停住了,想跳过当前函数finish
想一次性跑到下一个断点continue
想看哪个函数调用了我backtrace(栈回溯)

🔁 示例:实战流程一览

(gdb) file ./dtof
(gdb) break main
(gdb) break sensor.c:128
(gdb) run
# 停在 main
(gdb) next
(gdb) print sensor_status
(gdb) continue
# 停在 sensor.c:128
(gdb) info registers
(gdb) bt
(gdb) frame 1
(gdb) info locals
(gdb) kill
(gdb) run arg1 arg2

❓你可能还关心的问题:

  • 💡为什么要 kill 后再 run

    因为 run 会杀掉当前进程,除非已经手动 kill 掉,否则 GDB 会提示你是否要重新运行。

  • ⚠️使用 run 会清空所有程序运行时状态,只保留断点。如果你想继续运行,就要用 continue


你说得对,我们来把**“栈回溯(Backtrace)”的内容补全并与整个调试流程融合起来,特别强调它在调试程序崩溃(如 Segmentation fault)**、分析函数调用链上的作用。


🧠 GDB 栈回溯(Backtrace)完整讲解(结合调试全流程)

栈回溯 = 调用栈追踪,告诉你当前函数是被谁调用的,一直追溯到 main()
非常适合用来分析程序崩溃的位置和原因,比如段错误、空指针、非法访问等问题。


🔍 常用命令

backtracebt — 显示函数调用栈

(gdb) backtrace

示例输出:

#0  crash_here (ptr=0x0) at main.c:42
#1  0x000000000040115a in do_work () at worker.c:88
#2  0x0000000000401204 in main () at main.c:112

含义:

帧编号函数名参数来源文件与行号
#0crash_here()ptr=0x0崩溃发生在 main.c:42
#1do_work()worker.c:88 调用
#2main()main.c:112 开始

frame n — 查看某一帧详细信息

(gdb) frame 1

这会切换到帧 #1,然后你可以查看局部变量或源码位置。

(gdb) info locals
(gdb) list

✅ 栈回溯扩展用法

  • 只看前 N 层:

    (gdb) bt 5
    
  • 查看指定线程的回溯(多线程调试用):

    (gdb) thread apply all bt
    

💡 在调试流程中何时使用?

🚨 程序崩溃时(Segmentation fault)

当程序因为空指针等非法访问崩溃时,会自动停在异常点:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401042 in crash_here (ptr=0x0) at main.c:42

此时你可以:

(gdb) bt           # 查看崩溃是怎么一步步调用来的
(gdb) frame 0      # 进入崩溃函数
(gdb) info locals  # 看看哪个变量为空

🧪 实战流程举例

(gdb) run
# 程序崩溃了:
# Program received signal SIGSEGV, Segmentation fault.(gdb) bt
#0  crash_here (ptr=0x0) at main.c:42
#1  do_work () at worker.c:88
#2  main () at main.c:112(gdb) frame 0
(gdb) info locals
(gdb) print ptr
$1 = 0x0(gdb) frame 1
(gdb) info args

这一步一步定位出,main()do_work()crash_here(),并且因为 ptr=0x0,所以 *ptr = 1 导致了段错误。


✅ 最佳实践建议

场景命令
程序崩溃btframe 0info locals
调试函数调用顺序bt
查看 main 入口frame N (N 最大值)

🧩 集成进完整调试流程

在前面的调试流程中加入:

(gdb) run
# 程序崩溃后自动停止(gdb) bt                # 栈回溯
(gdb) frame 0           # 查看当前函数
(gdb) info locals       # 当前函数的局部变量
(gdb) frame 1           # 上一层函数
(gdb) info args         # 传入参数
(gdb) continue          # 若不崩溃则继续运行

是否要我帮你把这整套流程做成 .gdbinit.gdb_cmds 文件,你只要运行 GDB 就自动完成断点设置 + 栈回溯?也可以给你写个调试助手脚本。

http://www.xdnf.cn/news/14169.html

相关文章:

  • App渠道效果怎么统计和对比,有哪些实用方法和工具?
  • ROS的tf_tree中的节点含义详解
  • QGraphicsView
  • 【GESP真题解析】第 6 集 GESP 四级 2023 年 9 月编程题 1:进制转换
  • 【wvp-pro-gb28181】新建CallIdHeader失败的原因解析记录
  • 自动化KVM虚拟机创建脚本详解:从模板到高效部署的线上实践!
  • 【笔记】在新版本 Windows 系统安装回 Windows Subsystem for Android(WSA)
  • 「从实验室到工程现场:机器学习赋能智能水泥基复合材料研发全流程解析」
  • 表达式的自动类型转换
  • [Latex排版] 解决Something‘s wrong--perhaps a missing \item. 问题
  • 车辆车架号查询接口如何用Python实现调用?
  • 算法学习笔记:3.广度优先搜索 (BFS)——二叉树的层序遍历
  • 109.临时解决401错误
  • 线性三角波连续调频毫米波雷达目标识别
  • 【Vue2+antd 表格一直loading的问题】是赋值原因
  • Java 项目中实现统一的 追踪ID,traceId实现分布式系统追踪
  • 贵州建筑安全员C证理论考试题库
  • CHS和LBA的地址与的磁盘关联
  • C# 中委托和事件的深度剖析与应用场景
  • 求解偏微分方程组的通解
  • 小智AI为何要用MQTT+UDP?怎么接入MQTT?
  • Spring Boot 启动原理(SpringApplication.run(...) 流程)
  • 【Playwright MCP 实战分享:AI时代的浏览器自动化测试】
  • 销售预测的方法与模型(三)丨安全库存与再订货(补货)
  • AndroidMJ-基础-05
  • 数字人分身系统之数字人克隆功能板块开发,支持OEM
  • 一文了解sonar的搭建和使用
  • 基于openlayers开发北斗应用支撑平台
  • 1.2、SDH的复用结构
  • 2025年真实面试问题汇总(三)