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 独有的标志函数.

