软件调试和硬件调试都是调试,思路差不多,一些具体操作方式上有所差别。这是我在工作中总结的一些认识:
1.调试总的指导思想是,任何一个实验应该唯一说明一个问题。成功了,唯一的结论是推论是成功的;失败了,唯一的结论是推论是失败的。这都是带有唯一性的。实际操作中可能并不好做到,但其中的一个唯一应该是可以做到的。
2.由于软件硬件的耦合,杂散参数的影响。根本问题一样,可能现象每次发生都不一样。大胆的假设,仔细的求证是调试中是可以依托的一个大法宝。
3.经验总得来说,是一种实践过程中的总结和记忆。一般来讲,经验往往带有不精确性和一些大前提。在下一个项目或调试中应用这些经验,要确认这些不精确性和前提。如同定理一样,说三角形内角和是180度,在欧氏几何里是正确的,在曲面几何里就不正确了。所以,定理公理都是有应用前提,经验也逃脱不了这些问题。
一次和朋友去吃饭,他讲了个生动的例子:老婆和别人打八十分。那个算得精啊,每张牌都记住了算到了,准备把手里的一对AA,KK给出了。拖拉机啊。出去了就被别人给灭了,原来她还以为在打两幅牌的,他们在打得是三幅牌的……
也是够悲催的。
4.要对调试的系统的原理比较熟悉。不熟悉是不行的,考虑问题很可能就没有边界和方向。这也怀疑那也怀疑,变成了什么都怀疑,迷失了方向,面也太大了,不利于问题的解决。
5.现象的分析。解决问题都是从现象入手,现象要分清楚主次。结合设计的原理,分析出现象之间的关系,抓主要矛盾。次要现象很可能在主要现象解决后,伴随着一起消失。
6.缩小包围圈。有时候问题过于复杂,现象五花八门,可考虑剥洋葱的办法。试探性的去逼近核心问题。比如说,一个溢出错误,很可能产生一系列的连锁反应。也并不是一定会出现。可试探性的增大缓冲区,调整栈,看看有没有缓解;或者缩小缓冲区和栈,试探性看看程序的反应。对问题的现象做到心中有数。
7.对比法,在遇到一些复杂的问题的时候,不能解决。若有参照物,也可以定位问题。但对比法要注意一点,只有条件相同或相近的情况下,系统结构相同或相近下才有意义。否则比较会大大的降低可比性以及结果的意义。比如说一个软件模块或硬件模块,在其他系统上正常,在本系统上不正常。可推测为使用的问题。输入参数、输出参数,动态运行的条件不满足。
9.置换法,这个比较简单,一个一个换,换到有问题的那个,问题解决了,自然也就定位问题的所在点了。也可以把目标系统的模块置换到正确的系统上,看看能不能正常工作。
10.分治法,分治法是分而治之,各个击破的方法。现象很多,按照原理将现象分类。相关联的现象可作为一组,综合考虑。
11.调试分层次,经常使用的功能,重要的核心功能应该先调试,而次要的,不常用的功能最后调试。
12.最后,细致的观察。观察可以区别两种差别不大的现象;可以明确经验的应用范围;可以解决一些非常棘手的问题。Jtag不是万能的,会影响程序的速度和执行的频度;printf影响 栈的深浅以及运行时序;示波器探头是个负载,信号可能驱动不起来……这些问题一般都是细微的现象,非常容易被忽视,唯有细致的观察仔细的思考才可以捕捉。