Page 168 - 《软件学报》2026年第7期
P. 168
宋壹 等: 基于异常检查点植入的软件缺陷定位方法 2853
语句进一步赋予更细粒度的风险值. 该工作的实验结果表明, EXPECT 方法能够明显超过现有最优的 SmartFL 技
术. 有关该工作的具体细节, 可查阅文献 [21].
尽管 EXPECT 实现了良好的缺陷定位效果, 该方法强烈依赖于待测程序中原本自带的异常处理语句, 当待测
程序中不含或仅含少量异常处理语句时, 其有效性将受到严重威胁. 具体而言, EXPECT 方法的关键是根据收集到
的异常触发流确定分歧点, 然后才能根据分歧点开展后续的语句风险值计算. 而收集有效异常触发信息的前提是
程序中含有一定数量的异常处理语句, 否则收集到的异常触发信息将十分稀疏甚至为空. 尽管软件开发最佳实践
往往推荐开发者在程序中设置有效的异常处理语句, 但该建议在许多情况下并不被遵循, 导致真实开源程序中仅
含少许甚至不含异常处理语句的情况十分常见. 我们对 GitHub 社区中的开源项目进行了调研, 进一步证实了这一
现象. 例如, 对 Java 社区流行的数学计算项目 Math 核心包 [41] 的 12 363 行代码进行扫描, 未发现开发者书写的异
常处理代码. 这表明, EXPECT 方法虽然实现了较好的缺陷定位效果, 但其对异常处理语句的依赖限制了其泛化
性. 因此, 如何在异常处理语句缺失这一十分常见的情况下, 依然能够利用程序异常信息在缺陷定位任务中的潜
力, 开展高效的缺陷定位, 是软件调试领域需要解决的一项重要问题.
2 基于检查点植入的软件缺陷定位方法 INSPECT
为了解决上述基于异常信息的缺陷定位技术在真实开源环境泛化性受限的挑战, 本文提出一种基于检查点植
入的软件缺陷定位方法 INSPECT, 通过自动植入检查点的方式使得在待测程序没有异常处理代码的情况下, 依然
能够采集到异常触发信息并将其作为观测程序运行中间状态的窗口, 进而收集得到完整的异常触发流, 以开展缺
陷定位. INSPECT 方法首先在待测程序上运行测试用例集, 根据实际输出和预期输出是否相同, 将所有测试用例
划分为通过测试用例和失败测试用例, 失败测试用例将作为输入, 驱动检查点植入、伪正确版本生成、异常触发
流收集及分歧点确定、程序语句风险值计算这 4 个步骤的开展, 如图 1 所示.
Statements_Begin_1
① 检查点植入 异 ④ 程序语句风险值
植入密度、 常 执 Begin: Checkpoint#i 计算
Try-catch块 触 行 Statements_End_1
粒度、规则
发 跟 End: Checkpoint#i_triggeredOrNot
原始 信 踪 启发式
待测 失败执行 息 ... 规则
程序 异常触发流 Statements_Ending
通过测试用例
在待测程序 SBFL
③ 异常触发流收集
上执行 ② 伪正确版本生成 及分歧点确定 Tie
执行 生成突变 历史版本 捆绑打破
测试用例集 异 Statements_Begin_1
其他分支 ... 常 执 Begin: Checkpoint#i
失败测试用例 触 行 Statements_End_1
伪正确
版本 发 跟 End: Checkpoint#i_triggeredOrNot
信 踪 ... 语句风险值
息 排序列表
通过执行 Statements_Ending
异常触发流
图 1 基于检查点植入的软件缺陷定位技术 INSPECT 流程图
2.1 检查点植入
如前文所述, 程序异常处理代码在缺陷定位任务中的作用是检查相应位置的代码是否触发异常, 因此植入的
异常处理代码也称为“检查点”. 从植入粒度、植入规则和植入密度这 3 个维度确定检查点植入的方法. 下面分别
予以详细介绍.
(1) 植入粒度. 检查点植入粒度是指每个检查点检查程序执行状态的范围. 为了确定所检查的范围内是否有异
常被触发, 并记录异常触发信息, 采用 Try 代码块的形式植入检查点. 因此, 检查点植入的粒度实际上是每个 Try
代码块所包裹和检查的程序语句范围. 程序开发是一个较为复杂的过程, 不同项目往往有各自不同的代码逻辑与
结构设计, 为了尽可能使得植入的 Try 代码块可以有效捕获到程序执行过程中触发的异常, 以更全面地反映程序
执行状态, 方法以函数为粒度植入 Try 代码块, 即每个被植入的检查点唯一对应一个程序函数, 其 Try 代码块包裹
该函数中的所有程序语句. 选择函数作为检查点植入的粒度有两个主要原因. 一方面, 假设采用更细的粒度进行检

