Page 56 - 《软件学报》2021年第9期
P. 56
2680 Journal of Software 软件学报 Vol.32, No.9, September 2021
• 低准确率问题
基于测试的缺陷自动修复技术依赖于测试提供程序规约过滤候选修复补丁.但实际中,测试通常比较弱 [22] ,
不能提供完整的程序规约,从而导致即使修复补丁通过测试也可能是不正确的(似真补丁),即修复工具会产生
[5]
过拟合补丁 [100,101] .李斌等人 已经针对该问题进行了详细的分析和讨论,本文不再赘述.
针对缺陷自动修复存在的上述两点问题,本文将其所面临的的挑战及对未来研究的展望总结如下.
(1) 定位提供的信息.目前的缺陷定位技术在缺陷自动修复框架中所起的作用是返回代码中的疑似语句,
指导补丁生成过程,两个过程相对独立而缺少交互.但是在实际开发者人工修复的过程中,并不是严
格遵循上述的过程,而是两者相互作用 [102] :定位的过程可以为修复提供出错的“原因”指导生成补丁;
反过来,修复可以进一步优化定位的结果.DirectFix 通过优先选取简单的语句进行修复,在一定程度
上打破了上述的修复范式.但实际上,定位所提供的信息依然有限.最新的研究 [103] 尝试应用自动修复
产生的补丁优化缺陷定位的准确率,但其实验效果相比最新的定位技术并无明显提升.在缺陷定位研
究领域,最新的一些研究工作通过概率模型推导程序出错原因.如何将类似信息反馈给补丁生成过程
作为有效指导,目前依然缺少探索;
(2) 启发式规则.大部分已有的自动修复技术依赖人工定义的启发式规则作为生成补丁的指导,然而已有
的启发式规则仅依赖单一数据特征,如代码的语法特征(DirectFix 将补丁修改的大小作为启发式规
则)或代码语义特征(GenProg 将补丁通过测试的数量作为启发式规则).单一的约束会导致补丁搜索
陷入局部最优,例如 GenProg 产生很多通过测试的似真补丁.因此,结合代码的多维度特征提出合适的
启发式规则用于引导补丁的生成,是提升补丁质量的重要途径;
(3) 补丁模板数量.基于补丁模板的修复方法通常依赖于人工定义好修复的模板,在补丁生成阶段,根据
条件逐一尝试.这种修复模式适用于修复比较常见的、开发者比较熟悉且容易定义的缺陷类型,例如
插入一个条件语句、替换一个变量等.对于存在复杂逻辑约束的缺陷类型而言并不容易定义,因此在
理论上,已有方法只能修复一些比较简单的缺陷.Noda 等人 [104] 将 ELIXIR 应用于实际的工业场景发
现,其有限的模板是限制其修复数量的一个重要原因.虽然最新提出的修复方法尝试自动从历史修复
中学习模板(例如 Genesis,GetaFix 等),但由于该类方法依赖大量重复的训练数据,其应用范围受到限
制,也是仅仅针对个别类型的缺陷.GenPat 通过从单个代码修改提取补丁模板,可以有效克服上述问
题,但目前也仅有少数缺陷可以通过该方式修复.其中的一个关键原因是,自动提取的模板质量低于
人工定义模板.所以,研究从少量数据自动学习高质量补丁模板并应用于修复真实缺陷,依然面临重
大挑战;
(4) 代码修改大小.已有的自动修复工具只针对修改比较小的缺陷类型,比如单行代码修改或单个函数代
码修改等.实际中的代码缺陷可能涉及多函数甚至多文件修改,或者涉及复杂的代码结构(例如循环).
尽管最新的工作已经开始探索程序多点修改,如 HERCULES,但其修复能力依然非常有限,仅修复多
点代码修改类似或相同的缺陷.如果被修改的多处代码需要完全不同的修改甚至存在相互依赖关系,
上述方法将无能为力.例如在程序 A点添加一个标记变量,在程序 B点对标记变量进行检查.除此之外,
已有的缺陷修复工具通常将代码修改的范围限定在有限的代码区间内(<5 行),这也是限制已有方法
召回率的重要原因.但扩大代码修改范围会导致补丁搜索难度增加,降低补丁的准确率.因此,在扩大
代码修改范围时,如何根据修改之间的依赖关系约束补丁空间,是其中的重要挑战;
(5) 代码复用粒度.从早期的 GenProg 修复方法开始,利用代码的重复性修复缺陷被证明是有效的.最新的
研究通过细粒度的代码复用实现了较大的效果提升,例如 ssFix,SimFix 等.然而,上述修复技术依然依
赖于较大段的重复代码(5 行~10 行).在实际的项目中,这样的重复代码并不总是存在.因此,如何在更
细粒度搜索并复用已有的代码用于合成新代码,是扩展现有补丁空间的有效手段.虽然基于组件的合
成方法(例如 SemFix)在理论上可以实现上述目标,但由于约束求解器并非针对该特定问题所设计,实
际求解得到的代码质量低、可读性差.所以,探索通过代码复用合成高质量的修复补丁,是提升修复召