本节书摘来自华章计算机《Effective Debugging:软件和系统调试的66个有效方法》一书中的第2章,第19节,作者[希]迪欧米迪斯·斯宾奈里斯(Diomidis Spinellis),爱飞翔 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
第19条:使调试任务自动化
我们或许会找到很多个与程序错误有关的因素,但是却没有办法轻易推断出究竟哪一个因素才是致使程序出错的真正原因。为了把这个原因找出来,我们可以编写一小段例程或脚本,把有可能使程序出错的所有情况全都搜索一遍。如果待搜索的情况比较多,不便于手工进行搜索,但是却能够通过循环来进行遍历,那么就可以考虑对其加以自动化。例如,如果想遍历的是500个字符,那么可以通过自动化的脚本来实现,然而如果要把用户可能会输入的所有字符串全都尝试一遍,那么采用自动化脚本就不太合适了。
下面举一个例子。假设在某次升级之后,我们发现,计算机执行which命令的速度比原来慢了,然而把那一串比较长的搜索路径(Windows和Unix系统用PATH变量来代表该路径)改成/usr/bin之后,which命令的速度又快了起来。于是问题就来了:在该路径的26个元素中,到底是哪一个元素拖慢了which命令的速度?下面这个Unix shell脚本,可以显示出which命令在单独采用路径中的每一个组成部分时,所分别消耗的时间(我们通过Cygwin,在Windows系统里面运行这个脚本)。
脚本所输出的其中一部分内容如下:
由此我们可以发现,问题出在只含有一个斜线符号(/)的元素上面,这个斜线不小心跑到which命令的搜索路径里面来了。然后,我们对which命令的执行方式进行追踪(参见第58条),于是就找到了问题的根源:由于which命令会在路径中的每个元素后面补充一个斜线,因此,本来只包含一个斜线的那个元素,在搜索的时候就相当于变成了双斜线(//),而Windows系统如果遇到了这种以双斜线开头的路径,则会触发查找网络驱动器的流程。
如果你正在调试的这款软件,很难通过脚本来执行穷举式的搜索,那么可以考虑在程序中嵌入一个小的例程,以实现相同的目标。该例程通过某种算法(例如,对某些值进行迭代),把有待测试的各种情况全都生成出来。此外,也可以考虑使程序从某个外部文件中,把这些有待测试的情况读取进来,这样就可以用更为复杂的脚本或执行日志中的某些数据来生成那个外部文件了。
最后,我们还可以用一些工具来评估代码,以检测其中的API违例、内存缓冲区溢出以及竞争条件等问题(参见第59条和第62条)。用了这些工具之后,原本只需几秒钟就能运行完的测试分析任务,现在可能需要几十分钟,然而这是值得等待的,因为它们毕竟能够帮你省下大量的时间。
要点
- 把寻找程序故障的过程自动化,使得计算机多费一些功夫去搜寻,从而节省你自己的宝贵时间。