在软件开发及维护过程中, 人工进行程序缺陷修复极大消耗和降低软件开发人员的精力和效率. 空指针引用作为程序缺陷中一类隐蔽缺陷的存在, 不易察觉和修复. 据研究表明空指针引用在缺陷数量中所占比例超过20%, 且修复平均时间达到20 min. 为了提高修复效率、降低修复成本, 自从2009年开始, 程序自动修复技术[1-4]成为研究热点, 根据总结分析已有的程序自动修复技术可分为基于启发式搜索、基于人工模板、基于语义约束和基于统计分析的修复技术[5]. 基于启发式搜索[6]和基于统计分析[7]的技术常被用来多类缺陷的通用修复策略的生成, 基于人工模板[8]的修复技术适用于特定缺陷的补丁生成, 基于语义约束修复策略[9]皆适用于两种情况. 但是由于造成程序缺陷的原因以及缺陷的影响范围存在不同, 对多类缺陷采取统一的修复策略可能会降低候选补丁的准确率, 所以针对某一特定的缺陷的修复更为有效.
为了实现空指针引用自动修复, 需要充分掌握程序间的依赖关系, 从而准确识别缺陷的修复位置, 采纳合理的修复方案. 而程序依赖图[10, 11]包含数据依赖和控制依赖两个不同层次的依赖关系的融合, 可以充分掌握程序中的依赖关系. 但是数据依赖是由程序语句中的定义使用关系来识别, 这就忽略了语义本身所赋予的依赖关系. 例如, (1) x=a+a; (2) z=y+x%2, 根据语法中的定义和使用关系, z数据依赖于{y,x}, 然而x%2≡0, 在(1)的前提下, x的取值并不会影响表达式x%2的值, 也就是说, 实际上z并不取决于x的值. 从语义上来说y+x%2中的y是唯一与z相关的变量, 程序依赖图从语法上分析可能并不能计算出精确的依赖集, 因此并不能排除这种虚假依赖. 这就表明程序依赖图所识别的数据依赖关系超过了所需的依赖关系, 需要考虑真正的依赖关系及其传播.
本文做出了以下贡献.
(1) 提出了基于抽象语义的程序依赖图的空指针引用分析方法. 利用对抽象语义关联性的衡量, 忽略所有与抽象属性的不关联的语句节点进一步优化程序依赖图, 获取空指针引用的数据和控制依赖关系, 为选取修复位置及修复策略提供所需信息.
(2) 提出赋值、约束、规避、转移4种修复策略. 根据不同空指针引用的引发原因及缺陷所影响的代码集合, 依靠上下文信息选择4种修复策略实现修复.
(3) 提出基于语义距离的候选补丁排序方法. 通过计算不同候选补丁与原程序之间语义距离, 比较不同补丁对原程序的影响, 把所获得的候选补丁按照语义距离由小到大排列, 推荐最优补丁.
本文的其余部分组织如下: 第1节阐述基于抽象语义的程序依赖图的构建; 第2节介绍空指针引用的4种修复策略; 第3节解释如何通过语义距离对候选补丁的排序; 第4节展开了一系列的实验对比讨论, 评估本文方法的有效性; 第5节对本文工作进行总结, 同时展望下一步的研究工作.
1 基于抽象语义的程序依赖图研究表明, 数据依赖关系和控制依赖关系可以获取程序上下文详细信息, 然而程序依赖图中数据依赖关系的分析通过变量的定义使用链仅分析变量语法上之间的关系, 并不能识别变量之间是否真正具有语义之间的关联. 具体语义的关联性的计算繁琐且耗时, 并且在程序修复过程中往往只关注所需某一种语义属性. 基于抽象语义的程序依赖图恰恰可以采用抽象属性对程序依赖图进行简化, 将虚假的数据依赖关系筛除, 准确分析与空指针或空对象相关的数据和控制依赖关系. 并且在下文的空指针引用的4种修复策略中, 可利用优化后的数据和控制依赖关系精确识别程序上下文完成修复. 在此过程中, 需采取某种抽象属性的语义关联性对特定的语义相关度进行近似计算, 而这也是将程序依赖图转换为基于抽象语义的程序依赖图[12-14]的关键. 以下是基于抽象语义的程序依赖图的相关概念.
定义1. 控制依赖关系. 给定控制流图
定义2. 数据依赖关系. 给定控制流图
定义3. 程序依赖图. 给定一个有向图
定义4. 抽象属性的数据依赖关系. 给定一个程序依赖图
把抽象语义代替具体语义分析程序语句关联性时, 可以将程序依赖图中包含的控制依赖关系和数据依赖关系进一步精炼, 获得基于抽象语义的程序依赖图
根据修复空指针引用的分析可知, 判定一个赋值语句或者方法调用中的所获得值是否是空值是追踪空指针的关键因素, 故设定抽象属性
例如, 示例1代表一个存在空指针引用的缺陷程序, cond为false, 且通过指针的传递在L7中造成空指针引用. 对于程序依赖图而言, 可以通过数据依赖边和控制依赖边构建出来如图1所示. 但是在分析过程中可以发现, 语句节点2、4、5和6并没有涉及空值的传递, 因此这4个语句节点与抽象属性
示例1. 存在空指针引用的缺陷程序
L1 public Mode analyzeAction(Boolean cond, Parser p, Mode type){
L2 ConstructParser construct = new ConstructParser();
L3 Action action = p.getAction();
L4 if (cond) {
L5 Parser parser = construct.getParser(type);
L6 action = parser.changeAction(); }
L7 Mode mode = action.mode;
L8 return mode;
L9 }
为了获得关于抽象属性
算法1. 构建基于抽象语义的程序依赖图的方法
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
通过基于抽象语义的程序依赖图获取程序内精确的依赖关系后, 将结合空指针引用修复策略进行修复. 为了避免对程序其他功能造成隐患, 减小缺陷修复所带来的副作用, 本文尽力在最小的程序代码范围内实现精确修复, 因此在修复过程中把对程序执行路径的影响程度作为评价标准, 根据其影响程度由小到大依次提出了赋值策略、约束策略、规避策略和转移策略4种修复策略.
2.1 赋值策略赋值策略主要是对缺陷变量通过类型适配进行赋值, 其修复方式分为两类: 第1类, 寻找缺陷变量的定义位置, 在定义位置上利用非空的值替换错误赋值; 第2类, 在缺陷变量使用之前, 预先进行判断缺陷变量是否为空, 若是则进行恰当赋值操作. 式(1)和式(2)分别代表这两类修复方式:
$ \frac{{DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;{l_{{\rm{def}}}}:v = \_\;\;l:v = new\_value\;;}}{{{l_{{\rm{def}}}} \to l}} $ | (1) |
$ \frac{{DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;c:v = = {\rm{null}}\;\;l:v = new\_value\;;}}{{{l_{{\rm{use}}}} \to {\text{if}}(c)\{ l\} \;{l_{{\rm{use}}}}}} $ | (2) |
其中,
替换缺陷变量的值new_value的选取分为4种: 第1种, 若缺陷点存在与返回值类型相同的活跃变量, new_value为该活跃变量; 第2种, 若v的类型为第三方API库, 则将修复位置的活跃变量与构造方法的形式参数的类型相比较, 选取最佳的构造方法的实例对象作为new_value; 第3种, 若v的类型为自定义类型且只有一个构造方法, 则new_value为当前构造方法实例对象, 若有多个构造方法, 则可以根据当前程序点的活跃变量与构造方法的参数匹配选择最佳构造方法的实例对象; 第4种, 若v 为有子类的自定义类型. 根据变量名与子类名之间相似度选择最佳匹配, 则该子类实例对象被选择为new_value.
2.2 约束策略约束策略是通过对缺陷变量的提前进行条件判断来约束后续程序的执行, 其修复方式分为两类: 第1类, 将受到缺陷变量影响的代码集合预先放入条件判断中, 保证在缺陷变量不为空的情况下代码集合才可执行; 第2类, 将受到缺陷变量影响的代码集合放入try语句中, 在缺陷变量出现异常时抛出空指针异常. 式(3)和式(4)分别表示这两类情况:
$ \frac{{DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;c:v! = {\rm{null}}\;\;ds(v) = \{ {l_1}, {l_2}, \cdots, {l_n}\} }}{{{l_{{\rm{use}}}} \to {\text{if}}(c)\{ ds(v)\} }} $ | (3) |
$ \frac{\begin{gathered} \;\;\;\;\;\;DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;ds(v) = \{ {l_1}, {l_2}, \cdots, {l_n}\} \\ l:{\text{try}}\{ ds(v)\} \;\;{\text{catch}}({\text{NullPointerException}}\;\;e)\{ \cdots\} \\ \end{gathered} }{{{l_{{\rm{use}}}} \to l}} $ | (4) |
其中, ds(v)代表由缺陷点传递的错误信息影响之后执行的语句集合, 可通过基于抽象语义的程序依赖图所获取的依赖关系识别出缺陷变量的影响语句集合.
2.3 规避策略规避策略根据不同情况添加适当中断语句, 转移当前方法的执行来避免空指针引用触发, 其修复方式可分为3类: 第1类, 若被缺陷变量所影响的代码集中包含return语句, 为了避免约束受影响代码集合时出现无返回值的情况, 则需在空条件判断中增加恰当返回值; 第2类, 若被缺陷变量所影响的代码集合中包含return语句, 也可将代码块放入try语句中, 将在catch 语句中增加适当返回值; 第3类, 若缺陷变量在循环的某次循环过程中出现, 可添加continue提前结束当前这次异常循环过程的执行. 其中恰当的返回值
$ \frac{\begin{gathered} \;\;\;\;\;\;\;DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;c:v = = {\rm{null}} \\ ds(v) = \{ {l_1}, {l_2}, \cdots, {l_n}\} \;\;l:{\text{return}}\;\;valu{e_{{\rm{return}}}}; \\ \end{gathered} }{{{l_{{\rm{use}}}}\xrightarrow{{{\rm{type}}({l_1} \sim {l_n})\; \in \;{\text{return}}}}{\text{if}}(c)\{ l\} \;{l_{{\rm{use}}}}}} $ | (5) |
$ \frac{\begin{gathered} DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;ds(v) = \{ {l_1}, {l_2}, \cdots, {l_n}\} \;\;l:{\text{try}}\{ ds(v)\} \; \\ {\text{catch}}({\text{NullPointerException}}\;e)\{ {\text{return}}\;valu{e_{{\rm{return}}}};\} \\ \end{gathered} }{{{l_{{\rm{use}}}}\xrightarrow{{{\rm{type}}({l_1} \sim {l_n})\; \in \;{\text{return}}}}l}} $ | (6) |
$ \frac{{DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;c:v = = {\rm{null}}\;}}{{{l_{{\rm{use}}}}\xrightarrow{{{\rm{type}}(d\_dep(v))\; \in \;{\text{loop}}}}{\text{if}}(c)\{ {\rm{continue}}\;;\} \;{l_{{\rm{use}}}}}} $ | (7) |
其中,
若空指针的来源作为参数传递进入方法中, 转移策略通过在空指针被引用之前添加判断条件, 在判断条件为真时将空指针异常抛给外部调用方法处理. 式(8)在缺陷变量为空时添加l语句将异常抛出, 由外部调用方法捕获处理.
$ \frac{\begin{gathered} DU({l_{{\rm{def}}}}, {l_{{\rm{use}}}}, v)\;\;c:v! = {\rm{null}}\;\;ds(v) = \{ {l_1}, {l_2}, \cdots, {l_n}\} \; \\ \;\;\;l:{\text{throw}}\;{\text{new}}\;{\text{NullPointerException(}}\cdots{\text{)}}\;;\;\; \\ \end{gathered} }{{{l_{{\rm{use}}}} \to {\text{if}}(c)\{ ds(v)\} \;{\text{else}}\{ \;l\;\} }} $ | (8) |
考虑修复程序需在最小范围内的改动来消除空指针引用, 提出算法2来描述4种修复策略的匹配方法. Step 1获取当前程序缺陷的上下文信息, 之后判定是否满足修复策略所需条件并应用对应的修复操作. 因赋值策略的修复是从根本上改变缺陷变量的值完成修复, 所以首先在Step 4中判断的赋值策略的条件是否满足. 在此之后为了避免空指针的触发, Steps 5−6通过提取特定的条件选取约束策略或规避策略. 当之前3种策略均不可获得正确补丁时, Step 7判定是否满足转移策略的修复条件, 实施对应的修复操作. 最后在Step 10中验证获得的补丁是否通过所有的测试用例获取候选补丁.
算法2. 4种修改策略的匹配方法
输入: G: semantic-based abstract program dependency graph
输出:
Begin
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
END
3 基于语义距离的补丁排序经过匹配修复模板实施修复操作之后, 为了优先获取高质量的候选补丁, 将定义一些的评判规则对补丁进行排序. 在基于静态分析的补丁评价规则中一般分为语义距离[15]和语法距离两种[16]. 但是由于基于修复模板的缺陷修复本身就是通过不同的修复方式总结出的不同修复策略[17], 通过语法距离评判修复补丁并不具有客观性, 因此在本文中选择基于语义距离对候选补丁进行排序.
补丁程序P'是对缺陷程序P进行有限的程序修改获得的, 在
$ \begin{split} &{d_\zeta }(P, P', T) =\\ &\quad \left\{ {\begin{array}{*{20}{c}} {\infty, \;\;\;\;{\text{if}}\;\forall LOC:P' \notin {R_{LOC}}(P)\;{\rm{or}}\;{T_{\rm sat}}\;{\rm{is}}\;{\rm{empty}}} \\ {\displaystyle \sum\limits_{t \in {T_{{\rm{sat}}}}} {(\left| {M - K} \right| + \sum\nolimits_{h = 0}^{min} {{\textit{diff}}({\eta _n}, \eta {'_n})\;),\;\;} } {\rm{otherwise}}} \end{array}} \right. \end{split}$ | (9) |
其中, M和K分别表示程序P和P'在T上执行路径的长度,
候选补丁P'和候选补丁P''为示例1的两个候选补丁, 分别代表两种不同的修复方式. 表1记录了一次测试用例中原程序与两个候选补丁的语义距离计算, 假设cond=true , p=p, type=type为输入参数, 因为参数和construct的值未改变, 故并未将其添加到表1中. 其中, loc为执行位置, 其余均为程序内变量. 从表1可以看出, 在示例1缺陷程序P中action和mode分别在代码行3和7被定义且赋值, 且action在代码行6中被重新赋值. 根据候选补丁P'和候选补丁P''中的代码来标记action和mode定义和赋值情况. 通过比较执行位置loc和程序变量状态的一致性, 在
代码1. 候选补丁P'
L1 public Mode analyzeAction(Boolean cond, Parser p, Mode type){L2 ConstructParser construct = new ConstructParser();
L3 Action action = p.getAction();L4 if (cond) {L5 Parser parser = construct.getParser(type);L6 action = parser.changeAction(); }L7(+) if (acyion == null) {L8(+) action = new Action(t); }L9 Mode mode= action.modeL10 return mode;L11 }
代码2. 候选补丁P''
L1 public Mode analyzeAction(Boolean cond, Parser p, Mode type){L2 ConstructParser construct = new ConstructParser();L3(−) Action action = p.getAction();L3(+) Action action = new Action (t);L4 if (cond) {L5 Parser parser = construct.getParser(type);L6 action = parser.changeAction(); }L7 Mode mode = action.mode;L8 return mode;L9 }
4 实验
基于本文方法, 我们实现了一个缺陷自动修复工具DTSFix, 图3为其界面展示. 为了验证该工具在空指针引用的有效性, 实验1在公开数据集Defects4J[18]中空指针引用上设计了相关实验, 与其他工具的修复效果进行对比. 实验结果表明DTSFix多修复9个缺陷, 平均节省人工修复时间180 min. 实验2则通过在开源的数据库管理工具DBeaver的修复过程中成功修复了67%的空指针引用, 成功证明在DTSFix在实际工程上的修复能力.
4.1 与其他修复工具的对比在实验1中, 将DTSFix与同样专门针对空指针引用的工具NPEFix[19]进行对比, 所采用数据集为Defects4J中空指针引用如表2所示, 其中Chart包含7个, Lang包含5个, Math包含3个. 通过表3中的实验结果中可以看出NPEFix仅能正确修复2个缺陷, 而DTSFix正确修复11个缺陷修复成功率为73.3%, 共产生候选补丁19个, 正确补丁个数为14个, 准确率为73.7%.
为了更好地获得正确补丁, 在DTSFix中加入了候选补丁的排序算法. 在表3中的CAP和COP_F分别为DTSFix中候选补丁的数量和候选补丁中第一个正确补丁的排名, 从COP_F中可以看出, 通过经过对候选补丁的进行语义距离排序后, 在已修复的12个缺陷中, 其中10个正确补丁位于候选补丁的排名第一位. 在含有多个候选补丁的5个缺陷中, 4个正确补丁经过排序后排名上升, 这表明基于语义距离的候选补丁排序能够较好地区分正确补丁与错误补丁, 从而有助于开发人员选择正确的补丁.
4.2 在实际工程上验证DTSFix的修复能力
为了验证DTSFix对实际Java工程中空指针引用缺陷的修复能力, 我们选取免费开源的数据库管理工具DBeaver进行实验. DBeaver可支持任何具有JDBC驱动程序数据库, 为开发人员和数据库管理人员提供支持. DTSJava[3]作为检测工具对DBeaver进行缺陷检测, 其中含有9个空指针引用缺陷. 给定COP为正确补丁的数量, CAP为候选补丁的数量, DEN为缺陷数量. 从表4可以看出, DTSFix成功修复了6个缺陷, 其中约束策略修复4个, 规避策略修复2个. 未修复的3个缺陷中其中2个缺陷并未成功获得候选补丁, 原因在于修复模板提出的不够充分, 需要进一步细化空指针引用缺陷的修复模板, 但DTSFix对DBeaver的修复结果仍然可以确定DTSFix对于实际应用软件具有非常有效的修复能力.
代码3展示了其中一个空指针引用修复示例, 经过缺陷检测后缺陷开始行为224行, 缺陷发生行为226行, 缺陷变量为forTable. 经过基于抽象语义的程序依赖图分析forTable的缺陷影响的代码集合为{225, 226, 227, 228}, 其中228为return语句. forTable来源于外部参数通过赋值策略无法获取合适的值, 且缺陷感染域中包含return语句不满足约束策略的使用条件, 最后通过规避策略, 寻找方法中含有与返回值同类型同名变量的值, 增添修复语句如代码4进行修复, 并通过DTSJava进行回归测试结果证明缺陷已被成功修复.
代码3. DBeave缺陷程序示例
…223 protected JDBCStatement prepareChildrenStatement(@NotNull JDBCSession session,224 @NotNull OceanbaseMySQLCatalog owner, @Nullable MySQLTableBase forTable) throws SQLException { 225 if (forTable instanceof OceanbaseMySQLView) {226 JDBCPreparedStatement dbStat = session227 .prepareStatement("desc" + owner.getName() + "." + forTable.getName());228 return dbStat; }…
代码4. DBeave缺陷示例修复补丁
…223 protected JDBCStatement prepareChildrenStatement(@NotNull JDBCSession session,224 @NotNull OceanbaseMySQLCatalog owner, @Nullable MySQLTableBase forTable) throws SQLException { + if (forTable==null){+ return (JDBCPreparedStatement)session.prepareStatement(sql.toString());+ }225 if (forTable instanceof OceanbaseMySQLView) {226 JDBCPreparedStatement dbStat = session227 .prepareStatement("desc" + owner.getName() + "." + forTable.getName());228 return dbStat; }…
5 结论与展望本文提出了一种基于抽象语义的程序依赖图的空指针引用的自动修复方法. 通过抽象属性对程序依赖图的剪枝构建一种基于抽象语义的程序依赖图, 在其掌握精确的控制依赖关系和基于抽象语义的数据依赖关系的基础上, 采用总结出来的赋值策略、约束策略、规避策略和转移策略4种策略完成修复. 最后利用基于语义距离的排序方法对候选补丁进行排序, 将高质量的候选补丁优先排列. 实验证明基于抽象语义的程序依赖图的空指针引用的自动修复方法针对空指针引用的修复能够保证在较好的准确率的情况下提供正确的修复补丁, 并且在实际工程中具有非常有效修复能力. 在未来的工作中, 将在基于抽象语义的程序依赖图的分析上进一步总结空指针引用的修复模板, 提升空指针引用的修复精度.
[1] |
Ye H, Martinez M, Durieux T, et al. A comprehensive study of automatic program repair on the QuixBugs benchmark. Journal of Systems and Software, 2021, 171: 110825. DOI:10.1016/j.jss.2020.110825 |
[2] |
Klieber W, Martins R, Steele R, et al. Automated code repair to ensure spatial memory safety. Proceedings of the 2021 IEEE/ACM International Workshop on Automated Program Repair (APR). Madrid: IEEE, 2021. 23–30.
|
[3] |
Campos D, Restivo A, Ferreira HS, et al. Automatic program repair as semantic suggestions: An empirical study. Proceedings of the 2021 14th IEEE Conference on Software Testing, Verification and Validation (ICST). Porto de Galinhas: IEEE, 2021. 217–228.
|
[4] |
李斌, 贺也平, 马恒太. 程序自动修复: 关键问题及技术. 软件学报, 2019, 30(2): 244-265. DOI:10.13328/j.cnki.jos.005657 |
[5] |
Villanueva OM, Trujillo L, Hernandez DE. Novelty search for automatic bug repair. Proceedings of the 2020 Genetic and Evolutionary Computation Conference. Cancún: Association for Computing Machinery, 2020. 1021–1028.
|
[6] |
White M, Tufano M, Martínez M, et al. Sorting and transforming program repair ingredients via deep learning code similarities. Proceedings of the 2019 IEEE 26th International Conference on Software Analysis, Evolution and Reengineering (SANER). Hangzhou: IEEE, 2019. 479–490.
|
[7] |
Liu K, Koyuncu A, Kim D, et al. TBar: Revisiting template-based automated program repair. Proceedings of the 28th ACM SIGSOFT International Symposium on Software Testing and Analysis. Beijing: Association for Computing Machinery, 2019. 31–42.
|
[8] |
Afzal A, Motwani M, Stolee KT, et al. SOSRepair: Expressive semantic search for real-world program repair. IEEE Transactions on Software Engineering, 2021, 47(10): 2162-2181. DOI:10.1109/TSE.2019.2944914 |
[9] |
Kanemitsu T, Higo Y, Kusumoto S. A visualization method of program dependency graph for identifying extract method opportunity. Proceedings of the 4th Workshop on Refactoring Tools. Waikiki: Association for Computing Machinery, 2011. 8–14.
|
[10] |
Agarwal S, Agrawal AP. An empirical study of control dependency and data dependency for large software systems. Proceedings of the 2014 5th International Conference—Confluence The Next Generation Information Technology Summit (Confluence). Noida: IEEE, 2014. 877–879.
|
[11] |
Noda K, Yokoyama H, Kikuchi S. Sirius: Static program repair with dependence graph-based systematic edit patterns. Proceedings of the 2021 IEEE International Conference on Software Maintenance and Evolution (ICSME). Luxembourg: IEEE, 2021. 437–447.
|
[12] |
Halder R, Cortesi A. Abstract program slicing on dependence condition graphs. Science of Computer Programming, 2013, 78(9): 1240-1263. DOI:10.1016/j.scico.2012.05.007 |
[13] |
Sukumaran S, Sreenivas A, Metta R. The dependence condition graph: Precise conditions for dependence between program points. Computer Languages, Systems & Structures, 2010, 36(1): 96-121. DOI:10.1016/j.cl.2009.04.001 |
[14] |
Dong YK, Wu M, Zhang L, et al. Priority measurement of patches for program repair based on semantic distance. Symmetry, 2020, 12(12): 2102. DOI:10.3390/sym12122102 |
[15] |
D’Antoni L, Samanta R, Singh R. QLOSE: Program repair with quantitative objectives. Proceedings of the 28th International Conference on Computer Aided Verification. Toronto: Springer, 2016. 383–401.
|
[16] |
Liu K, Kim D, Bissyandé TF, et al. Mining fix patterns for FindBugs violations. IEEE Transactions on Software Engineering, 2021, 47(1): 165-188. DOI:10.1109/TSE.2018.2884955 |
[17] |
Martinez M, Durieux T, Sommerard R, et al. Automatic repair of real bugs in Java: A large-scale experiment on the Defects4J dataset. Empirical Software Engineering, 2017, 22(4): 1936-1964. DOI:10.1007/s10664-016-9470-4 |
[18] |
Cornu B, Durieux T, Seinturier L, et al. NPEFix: Automatic runtime repair of null pointer exceptions in Java. arXiv:1512.07423, 2015.
|
[19] |
王淑栋, 尹文静, 董玉坤, 等. 面向顺序存储结构的数据流分析. 软件学报, 2020, 31(5): 1276-1293. DOI:10.13328/j.cnki.jos.005949 |