调试是确定错误根本原因并纠正此错误的过程。对很多程序员来说,调试是程序设计中最为困难的部分。
1、 调试概述
-
调试在软件质量中所扮演的角色
同测试一样,调试本身并不是改进代码质量的方法,而是诊断代码缺陷的一种方法。开发高质量软件产品的最佳途径是精确描述需求,完善设计,并使用高质量的代码编写规范,调试只是迫不得已时采用的手段。
-
调试效率的巨大差异
并不是每个人都知道怎么调试。不同的开发人员通过调试发现缺陷的速度区别很大。
-
让你有所收获的缺陷
- 理解你正在编写的程序
- 明确你犯了哪种类型的错误
- 从代码阅读者的角度分析代码质量
- 审视自己解决问题的方法
- 审视自己修正缺陷的方法
-
效率低下的调试方法
-
调试魔鬼指南
- 凭猜测找出缺陷
- 不要把时间浪费在理解问题上
- 用最唾手可得的方式修正错误
-
迷信式调试
即使某个错误初看似乎并不归咎于你,但出于自身利益,最好还是假设它的产生同你有关。
-
2、寻找缺陷
-
科学的调试方法
- 通过可重复的实验收集数据
- 根据相关数据的统计构造一个假说
- 设计一个实验来证明或反证这个假说
- 证明或反证一个假说
- 根据需要重复上述步骤
-
寻找缺陷的有效方法
- 将错误状态稳定下来
-
确定错误的来源
- 收集产生缺陷的相关数据
- 分析收集的数据,并构造对缺陷的假设
- 确定怎样去证实或证伪这个假设
- 按照上一条确定的方法对假设做出最终结论
- 修补缺陷
- 对所修补的地方进行测试
- 查找是否有类似错误
-
寻找缺陷的小建议
- 构造假设时,考虑所有的可用数据
- 提炼产生错误的测试用例
- 在自己的单元测试族中测试代码
- 利用可用的工具
- 采用多种不同的方法重现错误
- 用更多的数据生成更多的假设
- 利用否定性测试用例的结果
- 对可能的假设尝试头脑风暴
- 在桌上放一个记事本,把需要尝试的事情逐条列出
- 缩小嫌疑代码的范围
- 对之前出现过的缺陷的类和子程序保持警惕
- 检查最近修改过的代码
- 扩展嫌疑代码的范围
- 增量式集成
- 检查常见缺陷
- 同其他人讨论问题
- 抛开问题,休息一下
-
蛮力调试
- 对崩溃代码的设计和编码进行彻底检查
- 抛弃有问题的代码,从头开始设计和编程
- 抛弃整个程序,从头开始设计和编程
- 编译代码时生成全部的调试信息
- 在最为苛刻的警告级别中编译代码,不放过任何一个细微的编译器警告
- 全面执行单元测试,并将新代码隔离起来单独测试
- 开发自动化测试工具,通宵达旦的对代码进行测试
- 在调试器中手动遍历一个大循环,直到发现错误条件
- 在代码中加入打印、显示和其他日志记录语句
- 用另一个不同的编译器来编译代码
- 在另一个不同的环境里编译和运行程序
- 在代码运行部正确的时候,使用能够产生警告信息的特殊库或者执行环境来链接和运行代码
- 复制最终用户的完整系统配置信息
- 将新的代码分小段进行集成,对每段集成的代码进行完整的测试
-
消除语法错误
- 不要过分信任编译器信息中的行号
- 不要迷信编译器的信息
- 不要轻信编译器的第二条信息
- 分而治之
- 找出没有配对的注释或者引号
3、修正缺陷
减少出错几率的建议:
- 动手之前先理解问题
- 理解程序本身,而不仅仅是问题
- 验证对错误的分析
- 放松一下
- 保留最初的源代码
- 治本而不是治标
- 修改代码时一定要有恰当的理由
- 一次只做一个改动
- 检查自己的改动
- 增加能暴露问题的单元测试
- 搜索类似的缺陷
4、调试中的心理因素
- 心理趋向如何导致调试盲目
人总期望一个新的现象类似于他们见到过的某种现象。你指看到你希望看到的东西,因而忽视了他们之间的差别。当发现错误的时候,程序员对于需要检查的程序部分的选择会不同。高效的程序员们能够在调试代码时,对无关紧要的部分视而不见。
- 心理距离在调试中的作用
心理距离可以定义为区分两事物的难易程度。在调试时,要警惕哪些没有足够心理距离的相似变量名或者子程序名。而在编写代码的时候,应该为变量或子程序选择差别较大的字,从而避免此类问题发生。
5、调试工具
- 源代码比较工具
-
编译器的警告消息
- 将编译器的警告级别设置为最高级,尽可能不放过任何一个警告,然后修正编译器报告的全部错误
- 用对付错误的态度来处理警告
- 在项目组范围内使用统一的编译设置
- 增强的语法检查和逻辑检查
- 执行性能剖测器
- 测试框架/脚手架
- 调试器
更多有关《代码大全 2》的读书笔记,请关注 :
http://tabalt.net/blog/code-complete-2-reading-notes/
本文链接:http://tabalt.net/blog/cc2-debugging/,转载请注明。
