Page 131 - 《软件学报》2026年第7期
P. 131

2816                                                       软件学报  2026  年第  37  卷第  7  期


                  3.1.3    TPL  特征库预处理
                    在初步构建的特征库中, 由于多个           C/C++ TPL  可能共享相同函数, 公共函数的广泛分布模糊了              TPL  边界, 影
                 响  SCA  的准确性. 为此, 我们进行了多阶段处理: 首先, 通过目录结构等线索初步过滤, 去除不属于特定                        TPL  的函
                 数 (图  4(c)); 随后, 将相似  TPL  归类, 并清理跨  TPL  共享的公共函数 (图    4(d)). 经过这些步骤, 每个   TPL  的特征更
                 加精准地反映其代码特性.
                    阶段  1: 基于明确线索的初步过滤. 我们首先为特征库的所有函数建立一张索引, 包含: (1) 出现频率: 包含相
                 同函数哈希的库的数量; (2) 路径信息: 库名称及函数在该库出现的路径. 遍历函数索引时, 对于出现频率为                            1  的函
                 数, 因其能够明确标识特定的         TPL, 充分反映   TPL  特性, 因此保留在源码摘要中; 而对于出现频率超过               1  的函数,
                 我们认为它们是公共函数, 并进行以下两步过滤操作. (a) 过滤外部库函数. 本步骤移除直接源自外部库的函数, 这
                 些函数可通过路径标识 (如“arangodb/3rdParty/abseil-cpp”) 明确区分. 由于其复用关系已在路径中体现, 因此不作
                 为  TPL  特征. 我们通过匹配路径中的外部标识 (如          3rdParty、external、deps 等) 来识别并移除这些外部库的函数.
                 (b) 过滤同一  TPL  不同存储库的重复函数. 在开源生态中, 同一           TPL  可能会有多个代码存储库, 这些存储库分布在
                 GitHub、GitLab  等平台, 由不同的组织或个人维护, 以满足跨平台、编程语言或特定应用场景的需求. 尽管它们的
                 物理位置不同, 但目录结构和函数实现往往高度相似. 如图                  6  所示, freetype [32] 的多个存储库包含相同的函数 (如
                 FT_CALLBACK_DEF). 为了消除这类公共函数的干扰, 我们对存储库的目录结构进行聚类分析 (K-means), 对于
                 目录结构相似且包含相同函数的库, 我们筛选出活跃的存储库作为代表, 并保留其中的函数, 剔除其他冗余库中的
                 重复函数.












                                                       (a) GitHub存储库











                                                        (b) GitLab存储库

                                       图 6 相同   C/C++ TPL  在不同存储库中的重复函数示例

                    阶段  2: 相似  TPL  归类与公共函数剔除. 除显式地引入外部代码外, 还存在隐式代码克隆现象, 即开发者直接
                 复制外部库代码而未标明来源           [13] . 此外, 一些基础算法 (如排序、查找) 常被开发者在不同项目中独立实现, 加剧
                 了函数跨库复用的现象        [15] . 这些公共函数因缺乏明确来源标识, 增加了区分难度. 为此, 我们通过分析共享这些函
                 数的  TPL  复用关系, 追踪代码来源, 揭示公共函数的真实归属.
                    首先, 通过公式     (1) 构建  TPL  相似度矩阵. 公式  (1) 中的  A  和  B  分别代表需要计算的两个     TPL  的函数哈希值
                 集合. 然后, 利用层次聚类 (hierarchical clustering) 算法将相似的   TPL  归为同一“家族”, 每个家族内部共享一定数
                 量的公共函数, 并包含各       TPL  独有的标志函数.
   126   127   128   129   130   131   132   133   134   135   136