[0021] 谓词P的真值率π(P)的取值范围为闭区间[0,1.0],将该区间化整为零,分成N段单独处理:取N=10000,得到[0,0.0001),[0.0001,0.0002),[0.0002,0.0003),[0.0003,0.004).....[0.9999,1.0]这10000个子区间。假设对于每个子区间[a,b](0<=a
[0022] 和
[0023] 那么在该子区间上,两个函数的曲线围成的等效面积就等于公式(4):
[0024]
[0025] 那么对应的有,在区间[0,1]上,两个函数围成的总面积就等于公式(5):
[0026]
[0027] 当区间数目取值越大,每个子区间的长度就越小,误差就越小,当N接近正无穷时,误差为0,二者完全相等:
[0028]
[0029] 因此有
[0030]
[0031] 公式(7)就是FDI算法最后的结果,其中S(P)表示谓词P的可疑度取值。
[0032] 本发明的有益效果是:该方法采用化整为零的方法,将所求面积分成N块,对每一块求值,最后将所有的N个子块的面积求和,即求得要求的总区间[0,1.0]上的总面积,也就是反映谓词和错误相关性的度量值。在一定范围内,N的值越高,计算的就越精确。本发明在将故障定位粒度细化至谓词级别的基础上,采用了基于非参数模型的统计方法,不需要被统计量符合某种已知分布模型,排除由于被统计数据的随机性对算法稳定性带来的影响,可以以提高定位精度。
[0033] 与CBI、SOBER以等主流算法的检测方式一样,为了验证算法的效果,采用Siemens Suite提供的标准的错误程序和对应的测试用例,对本发明方法进行了系统的测试。Siemens Suite是一组开源的用于评测软件故障定位方法和工具的数据集,自从2003年被引入用于评价NNQ法的有效性后,被广泛采用以评估错误定位技术的有效性。测试的最后结果证明:无论谓词的真值率的概率密度分布函数是否符合任何已知的参数化模型,本发明方法都能够对其进行有效的错误定位。
[0034] 对于SOBER无法处理的数据分布,该算法同样可以进行有效的处理:
[0035] 以下分别是SOBER和FDI的得出结果见下表6-1:
[0036] 表6-1 SOBER和FDI结果对比
[0037]
[0038] 从上表中可以看出在SOBER的计算结果中,第16号谓词在可疑列表排名中排名倒数,计算出的关键值最低,可见SOBER完全失效了;而在FDI中,第16号谓词排名为第一,计算出的关键值也达到了理论上最大的2.0,由此可见,本发明方法的效果非常令人满意。
[0039] 另外一个更加直观的实例:
[0040] Siemens Suite中的一个错误的replace.c的第14号谓词的真值率在成功和失败的运行中的频数分布如图2和图3。
[0041] 很明显,该数据根本不符合正态分布,但是如果非要按照SOBER的算法对数据进行处理的话,从图2和图3可知,对以上数据进行正态拟合后,本来差别很大的两组数据,拟合后二者的平均值非常接近,根据SOBER的计算方式,最后计算中得出的可疑度的值非常低,也就是说这种处理方式丢失了大量的数据,算法效果非常差。而如果采用了新的算法,那么根本不受分布是否符合正态分布的影响,都能计算出二者的面积差,因此新算法依旧有效。因此该算法可以解决SBOER无法完成的某些错误定位需求。
[0042] 与背景技术中的非参数化错误定位技术相比,本发明方法最大的优势在于计算成本非常低,算法的时间复杂度很低,对计算机的
硬件要求很低,因此实用性相对来说高很多,并且解决了混合编秩带来的大量误差。
[0043] 下面结合
附图和具体实施方式对本发明作详细说明。
附图说明
[0044] 图1是某一程序中某一谓词Pd的f(X|θp)和f(X|θf)在同一
坐标系中包络面积的函数图像。图中,横坐标表示真值率π(P),纵坐标表示某真值率占有的比例,即真值率为该值的概率。
[0045] 图2是某一程序在成功的执行中,谓词的频数分布图。
[0046] 图3是某一程序在失败的执行中,谓词的频数分布图。
[0047] 图4是本发明基于谓词频率统计的软件故障定位方法的
流程图。
具体实施方式
[0048] 参照图1-4。本发明基于谓词频率统计的软件故障定位方法具体步骤如下:
[0049] 对某程序一次运行中某一个谓词P多次赋值的记录采用真值率来描述:
[0050] 1、在程序的一次运行中,假设谓词P被记录为真的次数为nt,被记录为假的次数为nf,那么称:
[0051]
[0052] 为谓词P在这次执行中的真值(频)率。
[0053] 由极大似然法知,在样本足够多的情况下,P的真值频率无限接近P取值为真的概率,因此π(P)在一定程度上反映了谓词P在一次取值中为真的概率。
[0054] 2、假设对于一个程序,所有的测试用例集合为T,Tf表示失败的测试用例集合,Tp表示成功的测试用例集合,那么f(X|θp)和f(X|θf)分别表示Tf和Tp的真值率的概率密度函数。
[0055] 设f(X|θp)和f(X|θf)分别表示谓词P在成功的运行集合与失败的运行集合中的真值率的概率密度函数(见图1)。
[0056] 在这里我们无法用知道f(X|θp)和f(X|θf)符合何种已知的分布,因此无法像SBOER那样以参数化的方式描述。但是我们采用这两者相差的部分的面积:
[0057]
[0058] 作为衡量二者差异的关键值。
[0059] 因为f(X|θp)和f(X|θf)不符合任何已知的分布模型,因此我们无法知道f(X|θp)和f(X|θf)的函数表达式,因此本算法中采取了“化整为零,分段计算”的方式代替直接求表达式的方式:
[0060] 假设在总共X次的程序执行中,谓词P得到了Y个真值率记录(因为可能有的执行从不经过谓词P),有X>=Y。
[0061] 我们知道谓词P的真值率π(P)的取值范围为闭区间[0,1.0],因此我们可以将该区间化整为零,分成N段单独处理:例如取N=10000,我们就得到了[0,0.0001),[0.0001,0.0002),[0.0002,0.0003),[0.0003,0.004).....[0.9999,1.0]这10000个子区间。假设对于每个子区间[a,b](0<=a
[0062] 和
[0063] 那么在该子区间上,两个函数的曲线围成的等效面积就等于公式(4):
[0064]
[0065] 那么对应的有,在区间[0,1]上,两个函数围成的总面积就等于公式(5):
[0066]
[0067] 当区间数目取值越大,每个子区间的长度就越小,误差就越小,理论上,当N接近正无穷时,误差为0,二者完全相等:
[0068]
[0069] 因此有
[0070]
[0071] 公式(7)就是FDI算法最后要求的结果,其中S(P)表示谓词P的可疑度取值。
[0072] FDI为基于频率差异积分算法的软件错误定位技术的简称。
[0073] 综上所述,FDI的核心计算方法就是采用化整为零的方法,将所求面积分成N块,对每一块求值,最后将所有的N个子块的面积求和,即求得要求的总区间[0,1.0]上的总面积,也就是反映谓词和错误相关性的度量值。在一定范围内,N的值越高,计算的就越精确。但是考虑到实际应用当中,真值率的精度是有限的,一般为double类型,因此将区间无限缩小是毫无意义的。实践证明分段取1000到10000之间效果都很理想。
[0074] 本发明完成了一个自动测试系统,实现了对被测代码的自动检测,体现了发明的实用价值。
[0075] 该算法的实际实施流程如下:
[0076] (1)对被测软件源码进行插桩,插桩的主要目的为对程序中的每个谓词在每个测试用例的执行过程中进行信息统计,即统计谓词在每次运行中取值为真或假的次数。其方法为,通过对原始程序代码进行检测,在原始代码中每次出现程序分支的地方,即if...else处插入执行信息输出代码,当if中代码被执行时,此时谓词赋值为真一次,当else代码执行时,谓词取值为假一次。将获得的结果输出到日志文件中以备后续步骤使用。
[0077] (2)将插桩完毕的被测代码编译后,通过自动测试脚本运行所有的预定测试用例,便通过自动测试脚本收集程序谓词取值信息以及每个测试用例是否正确运行(即程序实际输出结果是否与测试用例中预测结果一致)。
[0078] (3)针对谓词取值信息和测试用例执行结果调用FDI算法进行分析。
[0079] 为了实现记录程序运行时谓词的历史赋值记录,我们采取了将被测程序进行自动语法分析然后进行自动转换的方法,重新生成新的程序。新的程序能够满足在运行的过程中,自动输出关键分支语句的谓词赋值记录,并且在功能上和以前的被测程序完全相同的要求。
[0080] 本发明采用了SHELL脚本和C/C++相辅相成,最终完成了所有步骤的一次执行。
[0081] (a)新的脚本的生成。
[0082] 对于每一个待测的程序,都有几千个对应的测试用例,而且在测试的过程中,往往要重复执行很多次。所以如果每个测试用例都要由人工控制是不可能完成的。
[0083] 因此采用测试脚本是必然的选择。然而每一个测试脚本要完成几千个测试用例的执行,所以基本上每个测试脚本都有几千行代码。通过人手动编写同样是不合理的。
[0084] 在此我们利用了Siemens Suite提供的初始脚本,在这个初始脚本的基础上,通过简单的C/C++代码进行文本读写操作,自动生成了新的测试脚本,用以对待测程序和转换后的程序的批量执行和测试。在后来的学习中发现,通过Linux自带的Bash脚本也也可以更加快捷的完成新脚本的生成。
[0085] (b)待测程序的预处理和转换。
[0086] 该功能模块的核心的处理算法由C/C++代码完成,在自动化的测试过程中,对该代码的编译和调用由Shell脚本完成。
[0087] (c)测试的执行。
[0088] 对于每个待测程序的多个错误版本的编译,对每个版本的上千个测试用例的执行,都由Shell命令调用实现。由于存在多个独立功能的Shell脚本,所以牵扯到多个Shell脚本之间的嵌套调用。
[0089] (d)对数据的收集和结果的计算。
[0090] 该功能模块就是整个测试系统的核心模块。
[0091] 在收集完待测程序执行的真值率的基础上,开始建模。在此处,采用了两种算法并行的方式,分别利用前面计算得出的真值率统计数据,各自算出不同的结果。这种方式充分利用了数据的复用,提高了算法效率,降低了算法成本,提高了计算价值。
[0092] 错误定位的核心算法都是由C/C++代码完成的。在自动化的测试过程中,核心算法的编译、运行和参数控制都是由SHELL脚本完成的。