调试九法
规则1理解系统
规则2制造失败
规则3不要想,而要看
规则4分而治之
规则5一次只改一个地方
规则6保持计跟踪
规则7检查插头
规则8获得全新观点
规则9如果你不修复bug,它将依然存在
规则一:理解系统
1 阅读手册
如果你是一位工程师,正在调试自己公司的产品,那么你需要读一读内部手册。工程师们设计它是用来做什么的?读一下功能说明以及所有的设计规范,研究一下图表、时序图和状态机。分析它们的代码,还要读一下注释。(是的,读一下注释,这非常重要。)一定要检查产品的设计。查明构建它的工程师们打算用它来做什么
2知道什么是正常的(基础知识)
知道什么是正常的可以帮助你意识到什么是异常的
3 知道工作流程
当你尝试寻找bug时,必须知道要查找的路线。开始时,你需要猜测在哪里把系统分隔开,以便隔离问题,这种猜测完全取决于你对系统功能划分的了解。你至少要大体上知道所有的模块和接口都是做什么的。
你应该知道系统中的所有API和通信接口都是用来交换什么数据的。还应该知道每个模块或程序如何处理它们通过这些接口收发的数据。如果代码是高度模块化或面向对象的,那么接口将很简单,模块也有良好的定义。观察接口就很容易解释你看到的东西是否正确。
当系统有一些部分是“黑盒子”时,这意味着你不知道它内部有什么,但应该知道它们如何与其他部分交互,这至少可以帮助判断问题是在内部还是外部。如果问题发生在黑盒子内部,你必须更换盒子,但如果问题出在外部,就可以修复它了。
4 了解工具
调试工具是用来观察系统的眼和耳,你必须选择正确的工具,正确地使用工具,并正确地解释得到的结果。很多工具提供了非常强大的功能,但只有精通它们的用户才了解。你越是精通工具,就越容易查明系统中发生了什么事情。要花时间学习与工具有关的一切,通常,查明系统行为的关键(参见规则3)是你的调试器设置得怎样,或者是否正确地触发了分析器。
我们还必须了解工具的局限性。走查源代码可以显示逻辑错误,但无法显示时序和多线程问题;剖析工具可以暴露出时序问题,但显示不出逻辑错误。模拟示波器(analog scope)可以看到噪声,但无法存储太多数据;数字逻辑分析器可以捕获大量的数据,但看不到噪声
5 查阅手册
小结:
- 阅读手册。它会告诉你在使用除草机时,要在除草头上涂润滑油,这样除草绳就不会被烧化。
- 仔细阅读每个细节。有关微处理器如何处理中断的详细信息就隐藏在数据手册的第37页。
- 掌握基础知识。电锯本来就会发出很大的噪声。
- 了解工作流程。引擎的转速可能与轮胎的转速不同,这是由传动轴造成的。
- 了解工具。弄清楚体温计的哪一端才是用来测量体温的,弄清楚Glitch-O-Matic逻辑分析器的强大功能是如何使用的。
- 查阅细节。连爱因斯坦都会去查阅细节,而Kneejerk却盲目相信自己的记忆力。
规则二:制造失败
1制造失败
重现失败的现象,并找到失败的规律
2 从头开始
试着从一个已知的状态开始,例如刚刚重启的计算机,或者是你一早步入车库时汽车的状态
3引发失败
在调试故障的时候,如果需要手工执行很多步骤,那么使这个过程自动化会很有帮助。
4 不要模拟失败
引发失败(正确)和模拟失败(错误)这二者之间存在着非常大的差别。正确的方法是模拟那些导致失败发生的条件。但是,不要试图模拟失败机理本身。
如果无法快速地再现它,那么不要为了使它出现而改变你的模拟环境。这样会产生新的配置,而不是原来发生错误的那个配置了。无论一个系统在哪种常规配置下发生故障(即使是间歇性故障),都要在该系统上使用该配置来查找问题。