SuperAPI AI 工具集

bug-detective

编程与开发

查看项目

更新于 10-15 14:24

技能介绍

Bug Detective 是一个系统化调试工作流技能,用于调查和解决代码错误、异常与失败。它提供结构化的调试方法和常见错误模式识别。

核心哲学

调试是一个科学的问题解决过程,需要:

  • 理解问题:清晰定义症状和预期行为
  • 收集证据:收集错误消息、日志、堆栈跟踪
  • 形成假设:根据证据推断可能原因
  • 验证假设:通过实验确认或排除原因
  • 解决问题:应用修复并验证

调试工作流

第 1 步:理解问题

开始调试前,明确以下信息:

  • 完整错误消息内容
  • 错误的确切位置(文件名和行号)
  • 复现步骤(如何触发错误)
  • 预期行为与实际行为
  • 环境信息(操作系统、版本、依赖)

问题模板:

  1. 确切的错误消息是什么?
  2. 错误发生在哪个文件和行?
  3. 如何复现此问题?提供详细步骤。
  4. 预期结果是什么?实际发生了什么?
  5. 最近哪些更改可能引入了此问题?

第 2 步:分析错误类型

根据错误类型选择调试策略:

  • 语法错误:代码无法解析,检查语法、括号匹配、引号
  • 导入错误:ModuleNotFoundError,检查模块安装、路径配置
  • 类型错误:TypeError,检查数据类型、类型转换
  • 属性错误:AttributeError,检查对象属性是否存在
  • 键错误:KeyError,检查字典键是否存在
  • 索引错误:IndexError,检查列表/数组索引范围
  • 空引用:NoneType/NullPointerException,检查变量是否为 None
  • 网络错误:ConnectionError/Timeout,检查网络连接、URL、超时设置
  • 权限错误:PermissionError,检查文件权限、用户权限
  • 资源错误:FileNotFoundError,检查文件路径是否存在

第 3 步:定位问题源

使用以下方法定位问题:

  1. 二分查找法:注释掉一半代码,检查问题是否仍然存在;逐步缩小范围直到找到问题代码
  2. 日志追踪:在关键位置添加 print/logging 语句;跟踪变量值变化;确认代码执行路径
  3. 断点调试:使用调试器断点功能;单步执行代码;检查变量状态
  4. 堆栈跟踪分析:从错误消息的堆栈跟踪中找到调用链;确定错误的直接原因;追溯到根本原因

第 4 步:形成并验证假设

假设框架: 假设:[问题描述] 导致 [错误现象] 验证步骤:

  1. [验证方法 1]
  2. [验证方法 2] 预期结果:
  • 如果假设正确:[预期现象]
  • 如果假设错误:[预期现象]

第 5 步:应用修复

修复后验证:

  • 原始错误已解决
  • 未引入新错误
  • 相关功能仍正常工作
  • 添加测试以防止回归

Python 常见错误模式

  1. 缩进错误
  2. 可变默认参数
  3. 循环中的闭包问题
  4. 迭代时修改列表
  5. 使用 is 进行字符串比较
  6. 忘记调用 super().init()

JavaScript/TypeScript 常见错误模式

  1. this 绑定问题
  2. 异步错误处理
  3. 对象引用比较

Bash/Zsh 常见错误模式

  1. 空格问题
# ❌ 赋值中不允许有空格
name = "John"  # 错误:尝试运行 'name' 命令

# ✅ 正确的赋值
name="John"

# ❌ 条件测试中缺少空格
if[$name -eq 1]; then  # 错误

# ✅ 正确
if [ $name -eq 1 ]; then
  1. 引号问题
# ❌ 单引号内变量不会展开
echo 'The value is $var'  # 输出:The value is $var

# ✅ 使用双引号
echo "The value is $var"  # 输出:The value is actual_value

# ❌ 使用反引号进行命令替换(容易混淆)
result=`command`

# ✅ 使用 $()
result=$(command)
  1. 未加引号的变量
# ❌ 未加引号的变量,空值会导致错误
rm -rf $dir/*  # 如果 dir 为空,删除当前目录下所有文件

# ✅ 始终引用变量
[ -n "$dir" ] && rm -rf "$dir"/*

# 或使用 set -u 防止未定义变量
set -u  # 或 set -o nounset
  1. 循环中的变量作用域
# ❌ 管道创建子 shell,外部变量不变
cat file.txt | while read line; do
    count=$((count + 1))  # 外部 count 不会改变
done
echo "Total: $count"  # 输出 0

# ✅ 使用进程替换或重定向
while read line; do
    count=$((count + 1))
done < file.txt
echo "Total: $count"  # 正确输出
  1. 数组操作
# ❌ 不正确的数组访问
arr=(1 2 3)
echo $arr[1]  # 输出 1[1]

# ✅ 正确的数组访问
echo ${arr[1]}  # 输出 2
echo ${arr[@]}  # 输出所有元素
echo ${#arr[@]} # 输出数组长度
  1. 字符串比较
# ✅ 在 POSIX `[` 测试中使用 `=`,在 Bash `[[ ]]` 测试中使用 `==`
if [ "$name" = "John" ]; then
if [[ "$name" == "John" ]]; then

# ❌ 使用 -eq 进行数值比较而不是 =
if [ $age = 18 ]; then  # 错误

# ✅ 使用算术运算符进行数值比较
if [ $age -eq 18 ]; then
if (( age == 18 )); then
  1. 命令失败后继续执行
# ❌ 命令失败后继续执行
cd /nonexistent
rm file.txt  # 删除当前目录中的 file.txt

# ✅ 使用 set -e 在错误时退出
set -e  # 或 set -o errexit
cd /nonexistent  # 脚本在此退出
rm file.txt

# 或检查命令是否成功
cd /nonexistent || exit 1

常用调试命令

Python pdb 调试器

python -m pdb script.py
pytest -x -vv tests/test_target.py

Node.js Inspector

node --inspect-brk app.js
node --trace-warnings app.js

Git Bisect

git bisect start
git bisect bad
git bisect good <known-good-commit>

Bash 调试

# 以调试模式运行脚本
bash -x script.sh  # 打印每个命令
bash -v script.sh  # 打印命令源代码
bash -n script.sh  # 语法检查,不执行

# 在脚本内启用调试
set -x  # 启用命令跟踪
set -v  # 启用详细模式
set -e  # 错误时退出
set -u  # 未定义变量时报错
set -o pipefail  # 管道中任何命令失败则失败

预防性调试

  1. 使用类型检查
  2. 输入验证
  3. 防御性编程
  4. 日志记录

调试检查清单

开始前

  • 获取完整错误消息
  • 记录错误的堆栈跟踪
  • 确认复现步骤
  • 理解预期行为

调试中

  • 检查最近的代码更改
  • 使用二分查找定位问题
  • 添加日志跟踪变量
  • 验证假设

解决后

  • 确认原始错误已修复
  • 测试相关功能
  • 添加测试以防止回归
  • 记录问题和解决方案

附加资源

参考文件

  • references/python-errors.md - Python 错误详情
  • references/javascript-errors.md - JavaScript/TypeScript 错误详情
  • references/shell-errors.md - Bash/Zsh 脚本错误详情
  • references/debugging-tools.md - 调试工具使用指南
  • references/common-patterns.md - 常见错误模式

示例文件

  • examples/debugging-workflow.py - 完整调试工作流示例
  • examples/error-handling-patterns.py - 错误处理模式
  • examples/debugging-workflow.sh - Shell 脚本调试示例