前置知识一、启用 GDB 调试编译期前提1. 编译必须带 -g作用生成调试信息变量名、行号、类型映射没有 -gGDB 只能看到机器指令地址看不到源码行号和变量名g -g -O0 -o app main.cpp-g生成调试信息-O0不优化变量不会被优化掉info locals才能看到值2. 用 CMake 构建时记得显式指定构建类型cmake -DCMAKE_BUILD_TYPEDebug .. # 自动 -g -O0 cmake -DCMAKE_BUILD_TYPERelease .. # 自动 -O3 -DNDEBUG调试困难 make调试用 Debug发布用 Release。3. MakefileCFLAGS -Wall -g CXXFLAGS -Wall -g二、启用 core dump崩溃时留下现场Linux 默认不生成 coreulimit -c为 0。三步开限制、设路径、关拦截。第一步开发板上开启 core 大小限制ulimit -c # 查看0 表示禁止生成 ulimit -c unlimited # 临时开启当前终端及其子进程有效.....剩下的用到了询问 ai 即可要点一、三种调试模式对比方式命令进程状态是否 attachGDB 控制活进程启动调试gdb ./apprun由 GDB 启动否是自己启动的附加调试gdb -p pid/attach pid已在运行是是接管的程序崩溃后 coregdb ./app core已崩溃否只读 core否无活进程补充完整崩溃定位还有dmesg addr2line这条不用 GDB 的路径适合“没 core、不能复现”的场景。二、三种模式的本质区别启动调试GDB --fork/exec-- 被调试进程GDB 是父进程被调试进程是子进程GDB 控制进程的创建和运行。附加调试GDB 使用-p或attach接管已运行进程GDB 接管一个“别人启动的”活进程。程序崩溃后 coreGDB --加载文件-- core 文件进程已死GDB 只读内存快照不控制任何进程。关键前两种 GDB 都控制一个进程启动的 or 接管的第三种 GDB 不控制任何进程只分析文件三、每种模式什么时候用场景用哪种理由开发阶段自己跑程序复现 bug启动调试能从头控制、设断点、单步板端程序已跑起来卡住/CPU 高/内存涨附加调试不能重启会丢现场只能接入看程序崩了有 core 文件程序崩溃后 core进程已死只能分析快照程序崩了没 core但能复现启动调试 run复现崩溃bt 看栈程序崩了没 core不能复现dmesg addr2line用 ip 地址反查源码行四、三种调试方法的写法方法 1启动调试gdb ./app (gdb) run (gdb) run --device /dev/video0 # 带参数启动说明GDB 自己 forkexec 启动被调试进程GDB 是父进程。能从头设断点、单步、控制运行。方法 2附加调试两种入口效果相同# 写法 A启动时直接指定 pid gdb -p 12345 写法 B先启动 gdb再 attach gdb (gdb) attach 12345说明GDB 接管一个已在运行的活进程ptrace PTRACE_ATTACH。两种入口效果完全一样只是命令行入口不同。附加后进程默认暂停看完用detach让进程继续不要 kill。方法 3事后 core 分析gdb ./app core # 或 gdb ./app core.12345说明进程已崩溃GDB 只加载 core 内存快照文件进行分析。不 attach 任何活进程不控制进程只读文件。五、调用栈与三个核心命令三种模式通用调用栈每调用一个函数栈上压一帧frame函数返回弹出帧编号从 0 开始#0 当前正在执行 / 崩溃发生的函数最顶层数字越大越靠外层调用者最底层是 mainbt / backtrace作用打印整个调用栈谁调了谁、崩在哪行用途崩溃后第一件事看调用链frame N作用把视角切到第 N 层看那一层的现场用途根因常在上层上层传了坏参数必须切上去看注意GDB 默认在 #0变量检查只能看当前帧info locals作用一次性列出当前帧所有局部变量及值用途快速看函数内状态比逐个 p 快注意只能看当前帧要先frame N切过去相关info args看参数info globals看全局变量六、三者配合流程崩溃定位标准动作# 1. 崩溃后先看调用栈 (gdb) bt #0 memcpy () #1 capture_frame (buf0x0, size614400) at v4l2_capture.cpp:88 #2 capture_thread () at v4l2_capture.cpp:150 2. 当前在 #0看不到 capture_frame 的局部变量切到 #1 (gdb) frame 1 #1 capture_frame (buf0x0, size614400) at v4l2_capture.cpp:88 3. 看 capture_frame 的局部变量 (gdb) info locals frame 0x7fff... ret -1 buf 0x0 - 找到根因buf 是空指针 4. 看源码第 88 行前后确认 buf 为什么是 0 (gdb) list结论memcpy 往空指针写 → 段错误根因是 buf 没分配成功mmap 失败没判空。七、附加调试结合 Linux 进程的四个场景场景 1进程卡住看它卡在哪ps aux | grep capture_app # 找 PID gdb -p pid # 附加 (gdb) info threads # 看所有线程状态 (gdb) thread 1 (gdb) bt # 看该线程卡在哪个函数 (gdb) frame 1 (gdb) info locals # 看卡住时变量值场景 2CPU 100%看哪个线程空转top -H -p pid # 按线程看 CPU gdb -p pid (gdb) info threads (gdb) thread 高 CPU 线程号 (gdb) bt # 定位到 spin_wait 等函数 (gdb) thread apply all bt # 一次看所有线程栈核心命令场景 3内存一直涨GDB 附加后用call malloc_stats()看堆统计真正泄漏定位靠 ASan-fsanitizeaddress或 Valgrindx86GDB 用途看可疑对象被谁持有(gdb) p some_object-buffer (gdb) p some_object-ref_count场景 4崩溃但没 coredmesg | tail -20 # 看 segfault 地址 # capture_app[1234]: segfault at 0 ip 0000000000401234 ... addr2line -e capture_app -f -C 0x401234 # 根据 ip 地址反查源码行 # 输出capture_frame /path/v4l2_capture.cpp:88 # 能复现则 gdb ./app 跑崩后 bt八、活进程调试与事后调试的区别对比项事后调试core活进程attach 附加调试栈的含义崩溃那一刻当前这一刻多线程崩溃线程的栈所有线程都有栈bt 范围默认当前线程默认当前线程thread apply all bt看全部变量值崩溃时的值活进程当前值可能被其他线程改附加后状态已死默认暂停需 continue 恢复退出quit 即可detach 让进程继续quit 退出关键附加调试时 GDB 暂停整个进程bt 看的是暂停那一刻的快照。看完用detach不要 kill 活进程。九、完整流程活进程多线程卡死排查# 1. 进程在 ps aux | grep capture_app top -H -p pid # 看线程某线程 0% CPU 卡住 2. 附加 gdb -p pid 3. 看所有线程一次看全部栈 (gdb) info threads (gdb) thread apply all bt 4. 选可疑线程 (gdb) thread 2 (gdb) bt #0 pthread_mutex_lock () #1 encoder::encode () at mpp_h264_encoder.cpp:200 (gdb) frame 1 (gdb) info locals mutex_ 0x... # 等这个锁 5. 找持锁线程 (gdb) thread 3 (gdb) bt #0 sleep () #1 capture_thread () at capture.cpp:80 - 持锁却在 sleep死锁 6. 进程继续跑 (gdb) detach (gdb) quit结论线程 2 等锁线程 3 持锁却 sleep → 死锁。修复调整锁的持有范围别在持锁时 sleep。十、常用命令速查命令说明info threads列出所有线程thread N切到第 N 个线程bt当前线程调用栈thread apply all bt所有线程调用栈多线程排查核心frame N切到栈第 N 层info locals当前帧所有局部变量info args当前帧函数参数p var打印变量list看当前源码detach脱离进程让活进程继续continue让暂停的进程继续十一、常见误区只在 #0 看变量 → 根因常在上层要 frame 切上一层frame 后忘了自己在哪层 → frame 会打印当前帧号info locals 看到空 → 被 -O2 优化掉用 -O0/-O1 编译egg编译使用g -g -O2 -o app main.cpp以为 bt 的 #0 是 main → #0 是当前/崩溃帧数字越大越靠外层附加后直接 quit 杀掉进程 → 先 detach 让程序继续运行再 quit 杀死 GDB 进程事后 core 当成 attach → core 分析不碰活进程只读文件十二、一句话总纲GDB 三种模式启动调试GDB 启动进程、附加调试attach 活进程、事后 core 分析只读崩溃快照不碰活进程。前两种 GDB 控制活进程第三种只分析文件。补充dmesg addr2line应对“没 core、不能复现”。核心命令bt打印整个调用栈frame N切到第 N 层info locals列当前帧局部变量。三者顺序配合bt 看全景 → 发现可疑层 → frame N 切过去 → info locals 看那层变量 → 找到根因常是上层传了坏参数。附加调试扩展info threads→thread N→bt→frame N→info locals。多线程用thread apply all bt一次看全快速发现“谁等锁、谁持锁、谁空转、谁阻塞 read”。附加调试记得 detach 而不是 kill。本质沿调用栈往上追看坏状态从哪层开始。
企业数字化 ERP 产品动态
相关推荐
HCIA第一次实操报告 一、拓扑图二、配置内容AR1:<Huawei>system-view[Huawei]sysname r1[r1]interface GigabitEthernet 0/0/0[r1-GigabitEthernet0/0/0]ip address 192.168.1.17 29[r1-GigabitEthernet0/0/0]quit[r1]interface GigabitEthernet 0/0/1[r1-GigabitEthernet0/0/1]ip address 1… · 2026/11/2 11:18:24
传统 SAP GUI 报表开发里,OSG 能不能直接读懂 Table Field 信息 可以,但这个答案必须加一个很重要的限定。
如果这里说的 OSG 是最近讨论很多的 Open SteamGate,那么它并不要求项目必须有 Fiori、OData、RAP、CDS,也不要求后端必须是 SAP Cloud。单纯的传统 ABAP Report、SAP GUI、SE38、Open SQL、DDIC Table 这条技术路线,本身就在 OS… · 2026/11/2 11:18:24
ClaudeCode的权限管理+Hook钩子相关知识(强制约束) 1.Skill/Hook/Routines三者在自动化层级上如何分层?{"hooks": {"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "echo checking... &&… · 2026/11/4 5:51:40
[高光谱]Any-Diff物理约束的的HSI图像生成 一、概述本文的特点是:将物理先验融入扩散模型,利用少量已知光谱波段,生成具有合理空间结构和光谱物理特征的完整高光谱图像。不同于简单图像修复,高光谱图像必须满足:空间合理性:建筑物、植被、道路等结构… · 2026/11/5 3:55:29
顶刊论文学习笔记 今日学习的论文:Genome architecture shapes transcriptional responses to topoisomerase depletion in C. elegans中文大意:基因组结构(基因排列方式)塑造了秀丽隐杆线虫对拓扑异构酶耗竭的转录响应。基础知识:基因表达的中心法… · 2026/11/5 3:55:29
会务管理系统后台:多角色权限与数据隔离方案设计 做会务管理后台时,权限是绕不开的模块。很多新手开发会简单理解权限 按钮显隐:有角色就展示菜单,没有就隐藏。 但会务系统有个典型特征:一套系统里会并行跑多个不同的学术会议、论坛活动。同一个 “签到管理” 菜单,A… · 2026/11/5 3:55:29
ADB 实战教程(AOSP/ROM 开发版) 面向 AOSP/ROM 开发者。按使用主线组织:连接 → 操作 App → 观测系统 → 模拟控制 → 性能诊断 → ROM 专属 → 实战速查。0. ADB 架构(30 秒理解)
三件套:PC 端 adb 客户端 → adb server(PC 常驻进程)→… · 2026/11/5 3:54:29
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38