Page 134 - 《软件学报》2026年第7期
P. 134
徐美秋 等: CAnalyzer: 面向 C/C++源代码的软件成分分析技术 2819
间接依赖
直 直
接 (include “Data.h”) 接
依 (include “Utility”) 依
赖 赖
图 8 文件依赖关系示例
● extern 关键字声明. 文件 A 通过“extern”声明引用文件 B 中的外部变量或函数, 从而允许文件 A 使用文件 B
中的全局变量或函数. 我们使用 Ctags 工具生成代码索引, 提取所有“extern”相关的语句, 记录变量和函数的名称
及其定义和声明位置. 通过解析这些信息, 可以确认文件 A 是否引用了文件 B 中的外部资源, 从而建立它们之间
的直接依赖关系.
(b) 间接依赖关系. 间接依赖指的是文件 A 未直接通过“#include”或“extern”引用文件 B, 而是通过中间文件形
成依赖链. 如图 8, Main.cpp 直接依赖 Utility.h 文件, 而 Utility.h 又依赖 Data.h 文件, 因此 Main.cpp 与 Data.h 之间
形成了间接依赖.
在分析间接依赖时, 我们关注文件 A 和文件 B 通过类、结构体、枚举等标识符的引用关系, 因为这些标识符
的定义和使用可以分布在不同文件中, 揭示文件间的关联性. 如果文件 A 使用了文件 B 中定义的标识符 (如类、
结构体或枚举), 并且它们的命名空间和作用域一致, 就可以推断文件 A 间接依赖于文件 B. 宏标识符和命名空间
标识符不在分析范围内, 因为宏仅在当前文件有效, 而命名空间可能在不同文件中重复或非连续定义, 不能准确表
示文件间的依赖关系.
CAnalyzer 的目标是在基于大规模特征库的场景下, 实现对 C/C++第三方库的高效自动化识别与依赖关系构
建, 为保证高可扩展性与执行稳定性, CAnalyzer 未采用程序级语义分析 (比如, 完整控制流和函数调用链分析), 以
避免此类分析带来的高时间与空间开销 (比如跨单元的指针别名分析与上下文敏感调用图构建). 我们认为, 引入
语义特征有望进一步提升依赖分析的精度. 未来工作中, 将探索在当前框架上实现轻量级语义增强, 在保持系统检
测效率与可部署性的同时, 进一步提高依赖分析的准确性与上下文感知能力.
(2) TPL 依赖检测. 检测过程如图 7(b) 所示, 通过文件依赖关系推断 TPL (即 TPL 成分模块) 之间的依赖关系.
(a) 消除内部依赖. 首先排除同一模块内文件的依赖关系. 若两个文件属于同一 TPL 模块, 则忽略其相互依赖,
避免内部依赖干扰分析结果.
(b) 建立外部依赖, 针对每个 TPL 模块, 分析其与其他模块间的文件依赖关系. 若模块 A 与模块 B 中的文件存
在直接或间接依赖, 则判定两模块间存在依赖关系. 为提高效率, 一旦确立模块间的依赖关系, 无需重复分析同一
模块对的其他文件依赖.
基于上述流程, 最终, CAnalyzer 输出目标 C/C++项目中复用的第三方库列表以及第三方库之间的依赖关系图.
4 评 估
本文提出的 CAnalyzer 是一种针对 C/C++源代码的软件成分分析工具, 检测目标代码中复用的 C/C++ TPL,
并分析 TPL 之间的依赖关系. 为了验证 CAnalyzer 的有效性, 我们设计了 5 个研究问题 (research question, RQ).

