mit einem Klick
debugging
遇到 bug、报错、崩溃或行为异常,需定位根因时。
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Menü
遇到 bug、报错、崩溃或行为异常,需定位根因时。
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
需求模糊、含隐藏假设或 X-Y problem,需先澄清再动手时。
审查代码(自己的或别人的),需有重点、分层次地看时。
Git 改动需编写规范提交信息时。
设计或改进错误处理与日志时。
在 Lion-Skills 仓库创建或修改 skill 时。
为代码标识符(变量/函数/类/文件/API/数据库字段)决定名字时。
Basierend auf der SOC-Berufsklassifikation
| 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 |