Page 311 - 《软件学报》2021年第7期
P. 311
张献 等:基于代码自然性的切片粒度缺陷预测方法 2229
征的重要性.
以上是对本文方法核心构成的可解释性的简要分析.至今,关于机器学习可解释性的研究依旧是一个难题.
我们也将在后续工作中继续加以探索.
(2) 代码自然性的讨论
本文将在切片级模块粒度上应用 CNDePor 方法并验证方法的有效性.由于涉及依赖性强的程序切片技术,
因而易使读者产生如下疑问:由于程序切片有别于自然语言特性,那么再提“代码自然性”是否合适?我们保持该
提法的思考是:① 对原始“代码自然性”思想的一种延续.本质上代码是一种人工制品.Hindle 等人最早提出的
软件代码的“自然性假设”受自然语言特点启发,因此所谓的“代码自然性”原本就是一种借鉴性说法.为延续这
种思想,本文保持了“代码自然性”这一提法.② 已有不少工作利用 NLP 方法来处理代码分析任务 [12,50] .虽然软
件代码有别于自然语言文本,但是它们有着诸多相似之处,例如都有语法规则约束、都由语法单元构成、都能
表示成序列/树/图等形式.文中作为重要基准的 VulDeePecker 方法,即是利用 NLP 领域中经典的双向 LSTM 模
型来学习切片代码段的语义特征,进而利用分类器进行缺陷识别.③ 语言序列的自然性是相对于语料库而言
的.语言模型可以视作是一个语言学习者,其在挖掘语料库的过程中会对常见的序列赋予更高的自然性,而罕见
的序列则反之.也就是说,语料库对语言模型起到决定性作用.一旦语料库构造完成后(如本文的切片粒度模块
数据集),便可以利用语言模型进行训练,进而判断给定序列(在该语料库上)的自然性.④ 语言模型可以捕获语
言间的依赖等规律与模式.通过挖掘语料库,语言模型(特别是神经语言模型)善于学习语言间的依赖规律和使
用模式,进而建模出语言序列的联合概率分布.对此说法的一个有力证据是语言模型在代码提示与补全 [54] 等任
务上取得的成功.
3 切片粒度模块生成方法及度量元设计
事实上,本文提出的 CNDePor 方法适用于不同粒度缺陷预测问题.然而经典的粗粒度方法难以精确地预测
缺陷区域,例如文件级、类级,使得实际应用中软件开发人员需要付出高昂的代码审查/测试成本.为此,我们将利
用 CNDePor 方法在面向语句的切片级粒度上进行细粒度缺陷预测应用.下面主要介绍切片粒度模块的生成方
法和面向此类模块的度量元设计.
3.1 模块生成方法
切片粒度软件模块的生成过程如图 4 所示.这一粒度分析的软件模块实质上是由一个或多个面向语句的
切片构成的代码序列.针对特定缺陷类型设计相关的切片准则,再通过软件历史信息标注生成的切片模块,便可
以构建出缺陷数据集.具体步骤如下 [30] .
步骤 1. 抽取库/API 函数调用.将库/API 函数调用分为两类:前向型和后向型.如果库/API 函数调用直接从
外部接收一个或多个输入,例如命令行、外部程序等,则它属于前向型.如果库/API 函数调用不从程序运行环境
中接收任何外部输入,则它属于后向型.
步骤 2. 生成关于库/API 函数调用中参数的切片.针对前向库/API 函数调用中的每个参数,生成一个或多个
前向切片;针对后向库/API 函数调用中的每个参数,生成一个或多个后向切片.需要注意的是,程序切片中的语
句可以从属多个函数,即切片范围可以逾越切片准则所在的函数.
步骤 3. 融合程序切片构成软件模块.针对已生成的切片集合,将从属于相同自定义函数的语句融合为一个
代码段,次序按语句在自定义函数中的原有出现顺序来设置.如果切片间存在重复语句,则删除.然后,将从属于
不同自定义函数的代码段融合为一个整体,构成一个软件模块.如果两个代码段对应的函数在某个切片中已有
明确顺序,则顺序保留;否则,代码段的顺序随机设置.
步骤 4. 标注软件模块的质量类型.依据缺陷数据库信息及人工审核方法,为每个软件模块分配一个质量标
签:“1”代表有缺陷;“0”代表无缺陷.需要注意的是,根据贡献者论文的叙述,实验数据集存在标签噪声,即相同的
软件模块可能拥有不同的质量标签.对于这种冲突情况,本文将其列为未知类型.