Automatic Software Repair: A Survey 自动软件修复:综述 (2)

原论文:Automatic Software Repair: A Survey 

原作者:Luca Gazzola, IEEE会员 Daniela Micucci, IEEE高级会员 Leonardo Mariani

2017年10月发表在IEEE Transactions on Software Engineering

原文链接:https://ieeexplore.ieee.org/document/8089448

译者:ClarkC.

此翻译已经原作者授权,翻译内容的准确性与原作者无关,引用请注明出处

感谢原文作者Leonardo Mariani教授提供翻译授权。鉴于原文很长,该翻译将分为六次上传。本次包含原文第5~6.1.1节的内容。原文中的参考文献可至附在开头与结尾的原文链接查看。

5. 定位

在本节中,我们将讨论程序修复技术使用的算法,用以找出程序中需要应用修复的位置。这是程序修复过程中的重要步骤,因为修复能否成功可能不仅取决于修复本身,还取决于修复的位置。

定位有两种主要方法:故障定位和修复处定位(fix locus localization)。故障定位技术的目的是识别故障语句。在这种情况下,修复就是将发现的错误语句修改正确。例如,在算法2中,故障定位技术将识别到第1行的if条件是生成修复的正确位置。

修复处定位技术的目的是检测能够观察和消除fault影响的语句。这些语句不一定是有错误的语句,但可能通过修改它们来使程序正确运行。事实上,错误行为通常可以通过补偿错误的影响而不是消除错误来修复。例如,与在算法2中修复第1行的条件不同,可以通过在第3行和第4行之间添加另一个if条件来修复,该条件在a等于0时打印a的值。因此,修复处定位技术可能会选定在第4行来生成可能补偿第1行故障的修复。

尽管两类方法有不同的目的,但在实践中,故障定位技术可能最终会识别出故障的位置,反之,修复处定位技术可能会最终确定出修复位置。(译者注:原文中这段的描述是相反的)

故障和修复处的定位策略通常都是临时定义的,与相应程序修复技术的能力和要求相关。例如,AFix[82]可以修复由CTrigger[83]专门定位的违反操作原子性的缺陷,CTrigger[83]结合跟踪分析和执行扰动来提取关于故障和错误代码区域的信息。

当需要了解该方法时,我们将故障定位策略与修复技术一起描述。在本节中,我们讨论了一些已被多种技术利用的定位方法。在整篇论文中,我们都会参考这些方法。

 

5.1 故障定位

程序修复技术广泛使用基于频谱的故障定位(Spectrum-Based Fault Localization,SBFL)[84]作为通用机制来定位可能有故障的语句。

SBFL利用测试期间收集的软件行为信息来识别可能有故障的程序元素。特别是,SBFL根据对通过和失败测试所涵盖的程序实体的分析,生成一个程序元素的列表,这些元素根据其出错的可能性进行排序[6],[85],[86]。一般情况下,由多个失败的测试用例和极少的成功测试用例执行的程序元素很可能是错误的,反之亦然,由多个通过和极少(或没有)失败的程序元素很可能是正确的。定位可以考虑不同类型和粒度的程序实体,如语句、分支和路径。故障定位和程序修复通常工作在同一粒度级别,即如果程序修复技术在程序语句级别工作,则用于故障定位的SBFL算法也在同级别工作。

我们分析了利用SBFL的文献,发现迄今为止,四种故障定位方法的使用频率最高:GenProg中定义的故障定位算法[87],[88](使用SBFL的文献的32%),Tarantula [6](18%),Ochiai[89](18%)和Jaccard [90](5%)。因此,为了说明SBFL是如何工作的,我们描述了这四种技术如何在算法6所示的错误程序中执行。

SBFL需要有测试套件,并且包含通过的测试用例和失败的测试用例。失败的测试会暴露需要定位和修复的故障。在这个例子中,我们假设一个测试套件有四个通过的测试用例和一个失败的测试用例。图4显示了错误的程序(左侧)、测试用例(列的标题,一对数字分别表示程序输入a和b的值)、每个测试用例执行的语句(每个执行的语句用X表示)、测试结果(P表示通过,F表示失败),以及Tarantula、Ochiai、GenProg的故障定位和Jaccard返回的可疑度分数。分数是介于0(最小可疑度)和1(最大可疑度)之间的值,用于对程序语句进行排序。我们使用灰色背景来突出显示由Tarantula、Ochiai和Jaccard中得分最高的语句。可以注意到,错误的打印语句出现在了所有技术的最可疑的语句集中。下面,我们将演示这四种技术是如何工作的。

我们使用failed(s)表示执行语句s的失败测试用例的数目,totalfailed表示测试套件中失败测试用例的总数,passed(s)表示执行语句s的成功测试用例的数目,totalpassed表示测试套件中成功测试用例的总数,execute(s)表示执行s的测试用例总数。

Tarantula计算的语句的可疑度是一个比值,即执行该语句的失败测试用例,与执行该语句的通过和失败测试用例的比例之和的比值。用公式来表示,语句s的可疑度suspT为:

Ochiai [89]计算语句的可疑度也是一个比值,即执行语句s的失败测试的数量,与失败的测试总数和执行s语句的用例总数之间乘积的平方根的比值。写成公式,对于语句s,其可疑度suspO为:

 GenProg [87]对每个语句的可疑度只有三种分数,分别表示该语句从未在失败的测试用例中执行,仅在失败的测试用例中执行,以及在失败和通过的测试用例中都执行。用公式来表示,语句s的可疑度suspG为:

 Jaccard [90]将语句s的可疑度计算为执行s的失败测试的数量,与执行s的测试总数和未执行s的失败测试之和的比值。写成公式,对于语句s,其可疑度suspJ为:

 

可以注意到,某语句在失败的测试中执行次数越多,其在Tarantula,Ochiai和Jaccard的得分就越高。反之亦然,某语句在通过的测试中执行次数越多,在这三种算法中的得分就越低。尽管只有三个分值,但GenProg的故障定位也遵循类似的模式。特别是,所有技术都在语句执行没有失败的测试时给出0分,而对于仅在所有失败的测试中执行的语句给出1分。在图4所示的示例中,由于while循环中的语句没有在失败的测试用例中执行,因此给出最低可疑度分。if语句的可疑度得分不是0,因为所有测试用例(包括失败的测试用例)都执行了该语句。最后,最可疑的语句是if条件的分支中的语句(GenProg故障定位中包括了if条件本身),其中包含有错误的语句。

图4:Tarantula,Ochiai,GenProg,Jaccard中SBFL的结果

在该示例中,使用这些故障定位技术之一的程序修复解决方案会重点关注在前三个语句来生成适当的修复。请注意,在示例中,最可疑的语句中包括了错误的语句,尽管通常不能保证会发生这种情况,也就是说,如果提供了不同的测试用例集,则错误的语句可能会排在较低的位置。Qi等人[91]初步研究了这些技术对修复算法有效性的影响,并且观察到Jaccard可以最好地支持自动程序修复技术。

 

5.2 修复处定位

修复处定位技术的目的是找到程序中适合生成修复的位置,而与故障的位置无关。其思想是,可以利用能识别故障影响的程序位置来补偿其影响。在下文中,我们描述了基于模型的修复处定位,它可以识别在面向对象软件中非法使用对象的语句[25];以及天使修复定位(Angelic Fix Localization),可以定位与if条件缺失或出错产生的故障相关的语句 [23]。

5.2.1 基于模型的修复处定位

基于模型的修复处定位已经在程序修复技术的背景下进行了实验,该技术可以修复导致错误使用类接口的缺陷[25],[92],[93],[94]。

基于模型的修复处定位首先运行通过的测试用例来收集运行时数据,然后挖掘表示程序在正确运行期间如何使用类的模型。挖掘到的模型由代表对象生命周期的有限状态机组成,即代表如何创建对象,何时调用这些对象的方法以及何时可以读写这些对象的字段。然后在执行失败的测试用例时动态检查挖掘到的模型。如果执行失败并违反了挖掘到的模型,则表明存在程序错误使用的对象,例如,将数据写入以只读模式打开的文件中的代码。生成修复过程所针对的位置就是错误使用对象的程序语句。请注意,这些语句尽管不一定是错误的,但显然是用于强制合法使用对象接口的合适位置。

尽管在软件修复方面并不总是有经验,但从正确执行中挖掘模型,然后检查失败执行并识别可能导致失败的代码元素的思想,与其他一些故障分析技术[14],[15]是一致的。

5.2.2 天使修复定位

天使修复定位针对可以通过修改程序中的if条件来修复的缺陷[23]。其思想是首先根据可疑程度来定位,然后忽略条件表达式的值,通过系统地强制失败的测试用例在决策点进入其他分支来确定哪些情况可能是错误的。例如,a等于0且b大于0的所有输入都会导致算法2失败,因为第1行的条件判定为假,就不会执行then分支。就算条件的判定结果为假,天使修复定位也会检查执行then分支时会发生的情况。执行then分支会使结果通过,因为程序会在打印0后终止,这对于a等于0且b大于0的所有输入都是正确的结果。这些使测试用例通过的条件值称为天使值(angelic values)。根据这个简单的策略,所有可能将失败的测试用例转换为成功的测试用例的决策点都被选择,并成为自动程序修复解决方案的可能目标,该解决方案旨在解决程序中的条件问题。

当尝试检测是否缺少if条件时,上述方法的工作方式略有不同。天使修复定位通过跳过单个(简单或复合)语句的执行来检查是否能将失败的测试用例转换为通过的测试用例。它会调查每条可疑语句的影响,并返回那些在失败的测试用例中应跳过执行的语句,作为生成修复的目标。这种情况下,修复应该包括添加新的if语句,这些if语句可以正确控制必须跳过的语句的执行。在if语句中生成适当的条件不是故障定位方法的一部分,而是修复过程的一部分。

改进版本的天使修复定位[95]扩展了先前的技术,能够在提取天使值时考虑所有程序表达式(而不仅仅是条件分支中的表达式)。首先通过使用SBFL识别可疑程序位置和相应的表达式,然后运行自定义的符号执行来确定天使值,同时用符号替换可疑的表达式来完成此操作。

要注意的是,天使修复定位返回的修复位置不一定是故障位置。天使修复定位所返回的位置,是可以通过修改或添加条件以掩盖或补偿缺陷影响的方式,来适时地改变执行流程的位置,并不一定与错误语句的位置相对应。

 

6. 生成修复

本节讨论用于自动生成程序修复的算法和相应的验证策略。所有的算法都是用一个待解的问题来逼近需要生成修复的问题。这意味着 的解决方案可能会解决需要生成修复的原始问题,但不能保证在实际应用中能够成功。因此,的解决方案被称为合理解(plausible solution

根据的定义和处理方式,我们将方法分为两大类:生成并验证方法和语义驱动方法。

生成并验证方法通过定义和探索的潜在解的空间来产生修正(请注意,可能包含解决和不解决的元素)。

语义驱动的方法(也称为按构造校正方法)以显式或隐式的形式对问题进行编码,一旦其找到了一个解决方案,则该解决方案就一定能解决

无论所使用的方法是哪一类,任何解决方案都会被报告给开发人员,他们会交叉检查其质量和正确性,并在必要时进一步详细说明,以获得完全满意和正确的修复。无论是否需要编辑自动生成的修复,自动修复的可用性已经可以帮助开发人员理解代码中的错误,并简化实际修复的实现。

修复技术可以设计为通用的或针对特定类型缺陷的。

通用技术在设计时并不针对特定类别的缺陷,并且有修复程序中的任何类别的缺陷的潜能。

针对特定类型故障的技术仅用于解决某些类型的缺陷,例如条件语句中的错误条件和缓冲区溢出。

原则上,针对特定类型故障的技术需要在更窄的范围和更高的修复效率之间取得平衡。

在本节的剩余部分,我们首先介绍生成并验证技术,然后介绍语义驱动的技术。我们首先介绍了描述每一类方法的关键概念,并从多个维度总结了其发展路线,然后讨论了各个方法,最后使用第4节中介绍的示例来举例说明。

 

6.1 生成并验证

生成并验证方法执行一个迭代的过程,如图5所示。该过程由两个主要活动组成,生成活动(产生针对问题的候选解决方案)和验证活动(用于验证生成的解决方案的正确性)。

图5:生成并验证修复过程

生成活动使用一组更改操作来修改原始程序P,并生成k个新程序添加到候选解决方案集中。对定位技术识别出的可疑位置进行修改的概率较高。更改操作可能具有不同的性质。


原子更改操作在单个点上修改P

预定义模板操作根据潜在的复杂预定义模式更改P

基于示例的模板操作的工作方式与预定义模板相同,但其模板是从历史数据(例如版本控制系统)中手动或自动提取的。

一些技术不仅将更改操作应用于P,还应用于候选解[22],[27],[36],[38],[63],[64],[96],[97]。这样,修改后的程序可以递增地累积由多个更改操作的应用所产生的变更。一种技术能够产生的所有候选解的整体集合表示其搜索空间。当中的每一个可能的元素都已被考虑或分配给修复过程的时间耗尽,该过程将不会产生的任何解决方案。

验证活动检查候选解决方案的正确性。目前为止,大多数生成和验证技术都是通过运行可用的测试用例来确定解决方案的正确性,也就是说,如果候选解决方案集中的程序s通过所有可用的测试用例,则s将作为P可能的修复返回给开发人员。作为验证的结果,候选解决方案集中的某些或所有元素可能会被丢弃,例如由于许多测试未通过而且在很大程度上不能令人满意的候选解决方案通常会被丢弃。

生成和验证活动可以根据两种主要策略执行:基于搜索策略和蛮力策略。这些策略在更改操作和候选解决方案的处理方式上有所不同。

基于搜索策略随机地,或在启发式或元启发式搜索算法的指导下,应用更改操作。

蛮力策略系统地产生每一个可能的更改,这些更改在所考虑的更改操作和定位算法下可以在一定的范围内获得。

请注意,在文献中,“基于搜索”标签既用于专门标识使用搜索算法的技术,又用于指示所有类别的生成和验证技术。本文中,我们仅使用“基于搜索“术语来表示使用搜索算法的生成并验证技术的子类。

表1和表2报告了实现生成并验证方法的技术(“技术“列)。表1包括使用原子更改操作生成修复的技术,表2包括使用基于模板的更改操作的技术。这些技术根据用于生成候选解决方案的搜索策略(”策略“列)、要解决的缺陷类型(“缺陷模型“列)和在尝试修复缺陷时修改的代码实体(”更改模型“列)进行分类。请注意,我们在“故障模型”列中使用标签“通用”来表示并非旨在解决特定缺陷类别的修复技术,其他标签则指特定缺陷类别。最后,“章节”列表示论文中描述了相应行中列出技术的章节号。在本节的其余部分,我们将讨论表中报告的案例。

表1:生成并验证技术-原子更改操作

表2:生成并验证技术-基于模板的更改操作

(未完待续)

若发现翻译问题,可直接评论或与我联系:[email protected]

原文链接:https://ieeexplore.ieee.org/document/8089448

译者:ClarkC.

此翻译已经原作者授权,翻译内容的准确性与原作者无关,引用请注明出处

猜你喜欢

转载自blog.csdn.net/ClarkCC/article/details/107216396