更新时间:2022-10-01 23:17:20
本节书摘来自华章计算机《Effective Debugging:软件和系统调试的66个有效方法》一书中的第1章,第3节,作者[希]迪欧米迪斯·斯宾奈里斯(Diomidis Spinellis),爱飞翔 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
修理电子设备的时候,我们首先要检查供电是否正常,也就是检查电流有没有从电源模块正确地流入该设备的电路中。在很多情况下,这项检查都能帮助我们找出问题。计算机程序与之类似,很多问题也可以通过对例程的入口点(entry point)与出口(exit)进行检查而得以确定。入口点就是前置条件(precondition),它指的是程序在即将执行例程时所具备的状态,以及传递给该例程的输入值,出口则是后置条件(postcondition),它指的是程序执行完例程之后的状态及其返回值。如果前置条件得不到满足,那说明用来设置这些前置条件的代码里面有错误,若是后置条件得不到满足,则说明该例程本身有问题。如果两者都正确,那么应该转向其他地方去寻找bug。
我们可以在例程开始的地方、调用例程的地方或关键算法开始执行的地方设置断点(参见第30条)。为了判断前置条件是否得到满足,我们应该仔细检查算法的参数,包括传入的参数值,调用方法时所针对的对象,以及可疑代码所使用的全局状态。尤其要注意以下几点:
然后,我们应该在例程结束的地方、调用完例程的地方或关键算法执行完毕的地方设置断点,以判断该例程的执行效果是否正确:
同样的方法也可以用在更为高层的操作与配置环境中。例如,如果要验证SQL语句是否正确地构建了某张表格,我们可以查看它所扫描的那些表格及视图,并且看看它构建出来的那张表格是什么样子。如果要判断基于文件的处理流程是否正确,我们可以检查其输入文件与输出文件。如果要调试某个构建在Web服务上面的操作,我们可以检查其中每项Web服务的输入与输出。如果要排解整个数据中心的故障,我们可以检查其中每个元素所需要的及所提供的机制是否正确,其中包括网络连接、DNS、共享存储、数据库以及中间件等。在这些情况下,我们都必须亲自验证(verify),而不能想当然地接受假设(assume)。