一键导入
debugging
遇到 bug、报错、崩溃或行为异常,需定位根因时。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
遇到 bug、报错、崩溃或行为异常,需定位根因时。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
需求模糊、含隐藏假设或 X-Y problem,需先澄清再动手时。
审查代码(自己的或别人的),需有重点、分层次地看时。
Git 改动需编写规范提交信息时。
设计或改进错误处理与日志时。
在 Lion-Skills 仓库创建或修改 skill 时。
为代码标识符(变量/函数/类/文件/API/数据库字段)决定名字时。
| name | debugging |
| description | 遇到 bug、报错、崩溃或行为异常,需定位根因时。 |
用科学方法定位 bug 的根因,而不是凭直觉乱改碰运气。核心:调试是观察 → 假设 → 设计实验验证 → 缩小范围 → 定位根因的循环,每一步都有依据。改到"不报错"不算修好——那可能只是把症状盖住了,根因还在。
不该用:行为符合预期的"不是 bug"(先确认是不是 bug,别把功能当 bug 调);环境/部署问题(先排查是不是代码外原因)。
与相邻 skill 的边界:debugging 管定位根因(调查:复现、假设、二分、读堆栈),verify-and-fix 管修复与验证(改对:修病因不症状、防回归)。两者接力——debugging 找出"问题是什么、在哪",verify-and-fix 接手"怎么改对、怎么确认修好"。debugging 的终点(定位的根因)就是 verify-and-fix 的起点。
当 bug 报告太模糊时("页面打不开""功能不工作"却没给报错/复现步骤),先回到 clarifying-questions 的思路——要可观察的现象(报错信息、触发操作、环境、是所有情况还是特定情况)再分析。没有现象的调试就是盲猜。
报错信息(异常类型、消息、堆栈、行号)往往直接包含根因线索,是调试最便宜的情报。最常见、最浪费的错法是不看报错就凭直觉改——明明堆栈第 3 行写着 Cannot read 'id' of undefined at line 42,却跳过它去猜"是不是网络问题""是不是缓存"。
读报错的顺序:
读堆栈的技巧:堆栈常被框架/异步包装得很难读,几个技巧帮你找到真正的根因帧:
async/await、Promise、回调、事件循环的堆栈经常断开(一个错误在 setTimeout 里抛,堆栈却看不到触发它的代码)。现代运行时有 --async-stack-traces 或类似的异步堆栈支持,开启它;否则要在触发处手动打日志补全调用链。error.cause 或 originalError 里——别只看最外层,挖嵌套的 cause 链。养成习惯:遇到 bug,第一件事是完整读一遍报错,而不是打开编辑器开始改。读不懂报错时,先查懂它(搜异常类型、读文档),别跳过。
不能稳定复现的 bug 几乎无法调试——你改了不知道有没有效,因为"不报错"可能是修好了,也可能是这次没触发。调试前先建立可复现:
不稳定复现的 bug(偶发)尤其要先攻克复现——它通常意味着有隐含条件没找到(并发时序、特定数据、资源竞争、时间相关)。找这个条件本身就是定位根因的关键。
反例:bug 偶发,你直接多加几个 try/catch 把可能出错的地方包起来"这样就不崩了"——错误被吞了看不见,但触发条件和根因一行没动,换个场景又炸,而且现在连报错都没了,更难查。
定位根因靠假设驱动,不是碰运气:
关键纪律:一次只验证一个假设。同时改多个变量,有效了也不知道是哪个起作用——这是 shotgun debugging(散弹枪式乱改)的典型。
什么样的假设是好假设:调试假设要具体且可证伪——能说"如果是 X 导致的,那应该观察到 Y",并且能设计实验验证 Y。
提不出具体假设,说明你对问题观察得不够——回到读报错、看运行时真实数据、建立复现,先把现象搞清楚。
当代码量大、不知问题在哪时,用二分法(git bisect 是经典实现):
二分法把"在 10000 行里找 bug"变成"log₂(10000) ≈ 13 次实验"。它不依赖理解代码,纯靠排除——当你读代码读不出问题时,二分是最有力的工具。
适用场景:回归 bug(之前好的现在坏了,用 git bisect 定位是哪次提交引入的)、不知问题模块的大型代码库、读代码陷入僵局。
"之前好的,现在坏了"是最容易调的一类 bug——你有一个已知正常的版本作参照,省掉了"重建预期行为"的功夫。策略:
"看了代码没发现问题"不等于"代码没问题"——也可能是运行时问题,代码逻辑没错,但运行时的数据/环境/状态让行为出错:
调试时两者都要查。如果代码读起来"没问题",转向查运行时:实际数据是什么样?打印/日志看一下真实值,而不是盯着代码猜。很多 bug 是"代码假设数据是 A,实际数据是 B"——光看代码发现不了,看真实数据立刻暴露。
| 问题 | 修法 |
|---|---|
| 不看报错就凭直觉猜 | 第一件事完整读报错(类型/消息/堆栈/行号) |
| 用 try/catch 把错误盖住当"修好" | 那是掩盖症状,先定位根因(见 verify-and-fix) |
| 乱改试错(同时改多处) | 一次只改一个变量、验证一个假设 |
| 不能复现就硬调 | 先建立最小复现,否则改了也不知道有没有效 |
| 改到"不报错"就停 | 不报错≠修好,可能只是症状被盖住,查清根因 |
| 只读代码不看运行时数据 | 代码没问题可能是运行时问题,打印/日志看真实值 |
| 陷入循环(A↔B),继续硬改 | 停,回到稳定状态,换方法(二分/重新假设) |
| 范围太大读代码读不出 | 用二分法快速缩小,不依赖理解代码 |
| 回归 bug 逐行读 diff 猜 | 用 git bisect 在好/坏提交间二分,锁定引入提交再看那一次的 diff |