调试时确定错误根本原因并纠正此错误的过程。
调试概述
让你有所收获的软件缺陷
- 理解你正在编写的程序;
- 明确你犯了哪种类型的错误;
- 从代码的阅读者的角度分析代码质量;
- 审视自己解决问题的方法;
- 审视自己修正缺陷的方法;
寻找缺陷
科学的调试方法在运用经典的科学调试方法时,你会经历如下步骤:
- 通过可重复的试验收集数据;
- 根据相关数据的统计构造一个假说;
- 设计一个实验来证明或反证则会个假说;
- 证明或反正假说;
- 根据需要重复上面的步骤。
寻找缺陷的有效方法:
- 将错误状态稳定下来;
- 确定错误的来源;
- 收集产生缺陷的相关数据;
- 分析所收集的数据,并构造对缺陷的假设;
- 确定怎样去验证或证伪这个假设,可以对程序进行测试或是通过检查代码;
- 按照上一步确定的方法对假设做出最终结论;
- 修补缺陷;
- 对所修补的地方进行测试;
- 查找是否还有类似的错误。
寻找缺陷的一些小建议
- 在钩爪假设时考虑所有的可用数据;
- 提炼产生错误的测试用例;
- 在自己的单元测试族中测试代码;
- 利用可用的工具;
- 采用多种不同的方法重现错误;
- 用更多的数据生成更多的假设;
- 利用否定性测试用例的结果;
- 对可能的假设尝试头脑风暴;
- 在桌上放一个记事本,把需要尝试的事情逐条列出;
- 缩小嫌疑代码的范围;
- 对之前出现过缺陷的类和子程序保持警惕;
- 检查最近修改过的代码;
- 扩展嫌疑代码的范围;
- 增量式集成;
- 检查常见缺陷;
- 同其他人讨论问题;
- 抛开问题,休息一下。
修正缺陷
- 在动手之前要理解问题;
- 理解程序本身,而不仅仅时问题;
- 验证对错误的分析;
- 放松一下;
- 保存最初的原代码;
- 治本,而不是治标;
- 修改代码时一定要有恰当的理由;
- 一次只做一个改动;
- 检查自己的改动;
- 增加能暴露问题的单元测试;
- 搜索类似的缺陷。
调试中的心理因素
调试工具
- 源代码比较工具;
- 编译器警告信息;
- 增强的语法检查和逻辑检查;
- 执行性能剖测器;
- 测试框架;
- 调试器;
核对表:关于调试的建议
寻找缺陷的方法
- [ ] 使用所有可用数据来构造你的假设;
- [ ] 不断提炼产生错误的测试用例;
- [ ] 在自己的单元测试族中测试代码;
- [ ] 借助可以获得的任何测试工具;
- [ ] 用不同的方式重现错误;
- [ ] 通过产生更多的数据来构造更多的假设;
- [ ] 利用证伪假设的测试结果;
- [ ] 用头脑风暴的方式找出所有可能的假设;
- [ ] 在桌上放一个记事本,把需要尝试的事情列出来;
- [ ] 缩小被怀疑有问题的代码区域;
- [ ] 对之前出现过问题的类和子程序保持警惕;
- [ ] 检查最近修改过的代码;
- [ ] 扩展被怀疑有问题的代码区域;
- [ ] 采用增量集成;
- [ ] 检查常见的缺陷;
- [ ] 和其他人一起讨论你的问题;
- [ ] 抛开问题休息一下;
- [ ] 在使用快速肮脏调试法的时候,要设置一个时间上限;
- [ ] 列出所有的蛮力调试方法,逐条应用。
解决语法错误的方法
- [ ] 不要太信任编译器信息中给出的行号;
- [ ] 不要太信任编译器信息;
- [ ] 不要太信任编译器给出的第二条错误信息;
- [ ] 分而治之,各个击破;
- [ ] 使用具有语法分析功能的编辑器来找出位置错误的注释和引号。
修正缺陷的方法
- [ ] 在动手之前先理解程序;
- [ ] 理解整个程序而非具体问题;
- [ ] 验证对错误的分析;
- [ ] 放松一下;
- [ ] 保存最初的源代码;
- [ ] 治本,而非治标;
- [ ] 只有当理由充分的时候采取修改代码;
- [ ] 一次只做一个改动;
- [ ] 检查自己所作的修订;
- [ ] 添加单元测试来暴露代码中的缺陷;
- [ ] 找出类似的缺陷。
调试的一般方法
- [ ] 你是否会把调试看做时能让你更好地理解程序、错误代码质量和解决问题方法的良机?
- [ ] 你是否会避免采用随机尝试查找错误或迷信式的调试方法?
- [ ] 你是否假设错误是你自己造成的?
- [ ] 你是否使用了科学的方法来寻找缺陷?
- [ ] 你在寻找缺陷的时候会使用多种不同的方法吗?还是每次都是用相同的方法?
- [ ] 你会验证你的修改是否正确吗?
- [ ] 你在调试中使用编译器警告信息、执行性能分析、利用测试框架和交互式调试方法吗?
要点
- 测试同整个软件开发的成败息息相关;
- 要想成功,系统化地查找和改正错误的方法至关重要;
- 再动手解决问题之前,要理解问题的根本;
- 将编译器警告级别设置为最严格,把警告信息所报告的错误都改正;
- 调试工具对软件开发而言是强有力的支持手段。