- 好的程序员知道他们在排错上花费的时间至少与写程序一样多,所以他们努力从自己的错误中学习。
- 对减少排错时间能有所帮助的技术包括:好的设计、好的风格、边界条件测试、代码中的断言和合理性检查、防御性程序设计、设计良好的界面、限制全局数据结构以及检查工具等。早期预防胜过事后治疗。
- 初学者都有一个倾向,那就是抱怨编译系统、或者程序库、或者除了他们的代码之外的 其他任何东西。有经验的程序员当然也希望能这样做,但是他们知道,实际上多半是他们自己的错。
- 排错涉及到一种逆向推理,就像侦破一个杀人谜案。
- 寻找熟悉的模式,典型错误。忘记对局部变量进行初始化是另一类容易识别的错误
- 检查最近的改动。如果在新版本里出现错误而旧版本原来没有,新代码一定是问题的一部分。
- 不要两次犯同样的错误。当你改正了一个错误后,应该问问自己是否在程序里其他地方也犯过同样错误。一旦你确定并更正了一个错误,就应该再想一想,你是否也清除了其他类似的错误。
- 有时你看到的代码实际上是你自己的意愿,而不是你实际写出的东西。离开它一小段时间能够松弛你的误解,帮助代码显出其本来面目。
- 把你的代码解释给别人。
- 把错误弄成可以重现的。第一步应该是设法保证你能够使错误按自己的要求重现。你应该花点时间,设法构造输入或者参数设置,
使自己能可靠地再现问题。例如输出随机数生成器的种子值,以保证你能产生同样的输出。
- 分而治之,问题局部化。能否把导致程序失败的输入弄得更小一点,或者更集中一点?采用二分检索的方式,丢掉一半输入,看看输出是否还是错的。如果不是,回到前面状态,丢掉输入的另一半。
- 研究错误的计数特性。有时失败的实例具有计数特征方面的模式
- 显示输出,使搜索局部化。如果你不能理解程序到底在做什么,弄清楚它最简单的而又代价低廉的方法就是加一些语句,使程序显示出更多的信息。用这种语句验证你对程序的理解或者你对什么东西可能出问题的想法
- 写一些简单的程序去测试你的假定,或者确认你对某些东西工作方式的理解。
- 源代码控制程序,如 R C S,能够跟踪代码的版本,使人可以看清哪些东西被修改过,还可以恢复原来版本,回到已知的状态。
- 保留记录。如果查找某个错误的过程花了一定时间,你可能就要开始忘记试验过的情况和已经学到的东西了。
- 例如花了大量时间在没有错误的地方寻找,由于测试程序本身有错,被测试的根本不是程序的正确版本,或者是忘记了在测试之前更新或者重新编译,等等。
- 存储器“流失”—不再使用的存储没有退还—是程序古怪行为的一个重要根源。另一个类似问题是忘记关闭文件,直到打开的文件占满了文件表,程序无法再打开新文件。带有这类漏洞的程序最终将奇怪地垮台,原因是它用光了所有资源,而特定的失败又是无法重现的。
- 不能始终重现的错误是最难对付的,应该先检查所有的变量是否都正确地进行了初始化。
- 如果在增加排错代码之后错误的行为改变了,甚至是消失了,那么它很可能就是一个存储分配错误,有许多输出函数,从 p r i n t f到对话窗口,在工作过程中都要分配存储,这些都能进一步把水搅混。