Page 264 - 《软件学报》2024年第4期
P. 264
1842 软件学报 2024 年第 35 卷第 4 期
tokens of defects and specific operation behaviors of repairing the tokens. A large number of defect patch data sets in open-source projects
contain a large amount of trainable data, and the paths constructed based on abstract syntax trees can effectively capture the program’s
structural information. Experimental results show that the model trained in this study can accurately predict defect code tokens and is
significantly better than the baseline methods based on statistics and machine learning. In addition, in order to verify that fine-grained
defect localization results can contribute to automatic defect repair, two kinds of program repair processes are designed based on the fine-
grained defect localization results. The processes are implemented by using code completion tools to predict the correct token or by
following heuristic rules to find appropriate code repair elements. The results show that both methods can effectively solve the overfitting
problem in automatic software defect repair.
Key words: defect localization; automatic defect repair; neural network
随着软件规模不断增大, 软件出现缺陷变得不可避免. 软件缺陷定位技术是软件调试活动中非常重要的任务
和研究课题. 准确的缺陷定位不仅可以减轻开发人员的工作负担, 而且作为缺陷自动修复技术的上游任务, 其准确
性的提升也能够进一步促进缺陷自动修复研究工作的研发 [1] .
已有研究表明, 现有的缺陷定位技术尚未被工业界的开发人员们广泛使用. 其主要原因是现有定位技术不能
够提供细粒度的定位结果 [2] . 具体而言, 现有技术主要关注于代码函数或语句级别的缺陷定位, 而开发人员们认为
仅提供一条可能出错的代码语句并不能够帮助他们快速准确地理解和修复缺陷. 理论上, 有两种可行的方案能够
弥补当前缺陷定位技术的不足: 一种是在提供粗粒度定位结果的同时提供缺陷的精确描述 (例如, 在第 x 行出现了
缓冲区溢出的错误); 另一种是提供细粒度的代码令牌 (code token) 级别的缺陷定位结果以及修改该令牌的操作行
为 (例如, 更新位于第 x 行第 y 列的布尔值“true”). 本文的工作采用第 2 条路线来弥补现有缺陷定位技术的不足.
缺陷定位为缺陷自动修复提供需要进行修正的代码位置, 然而现有的缺陷定位粒度不能为缺陷自动修复提供
很好的支撑. 一方面, 函数和语句级别的定位会使得缺陷修复工具在生成补丁时遇到搜索空间爆炸的问题, 导致修
复效率低下 [3] ; 另一方面, 定位工具的不准确导致修复工具在非缺陷位置处生成测试过拟合的补丁 (即通过测试但
不能正确修复缺陷的补丁). 这种补丁带来过拟合的问题 [4−8] 是缺陷自动修复技术面临的关键瓶颈 [9] . 图 1 展示了
源自 Defects4J 缺陷数据集 [10] 的 Closure-62 缺陷的标准补丁. 尽管当前缺陷定位工具能够定位到这条出错的条件
语句, 由于不了解该语句中出现错误的位置, 开发人员仍需要调查大量的变更实验来修复该缺陷. 类似地, 一个常
规的基于搜索的缺陷自动修复工具需要对该语句中的 12 个代码令牌 (即“excerpt”“equals”“LINE”“&&”“0”“<=”
“charno”“&&”“charno”“<”“sourceExcerpt”“length”) 进行多种修复尝试. 在这一过程中, 对非缺陷代码元素进行实
验将产生和验证众多无意义的补丁, 而编译与运行补丁通常极为耗时, 这将大大降低自动修复的效率. 此外, 修改
非缺陷元素会增加产生过拟合补丁的可能性. 图 1 的下半部分给出了 jKali 工具 [11] 针对此缺陷生成的过拟合补丁,
它删除了整个条件表达式. 由于真实程序中的测试套件往往不能够完整刻画程序正确行为的规约, 该补丁仍通过
了整个测试套件并造成过拟合补丁的产生. 总的来说, 缺陷定位是促进人工调试与缺陷自动修复的关键.
图 1 缺陷 Closure-62 的标准补丁以及 jKali 对其生成的过拟合补丁
针对上述问题, 本文提出一种基于深度学习的细粒度缺陷定位方法 BEEP (buggy code element predictor). 该方
法意在准确定位缺陷程序中需要被修改的导致缺陷的代码令牌, 因此能够较当前的缺陷定位方法 (至多提供语句
级别的定位结果) 提供更加细粒度的定位结果. 我们方法的基本假设与大多数基于机器学习的缺陷预测技术 [12] 的
共同假设相似, 即, 具有相似程序结构的缺陷程序往往涉及相同的错误代码元素 (令牌). 因此, 我们采用了抽象语
法树路径 (AST path) 的技术, 该技术已被证明能很好地学习到程序的语法结构特征 [13−16] . 我们方法的工作流程如
图 2 所示. 其总体上分为两个阶段, 即模型训练和令牌预测. 在训练阶段, 首先进行数据的预处理: 我们对大量的补