在 C/C++ 项目中,有些代码可以顺利通过编译,却不代表运行时一定没有问题。
比如下面这段代码:
int read_value(const int* data, std::size_t size, std::size_t index) {
if (index <= size) {
return data[index];
}
return 0;
}
它至少有两个潜在风险:
data 可能是空指针;
当 index == size 时,可能发生数组越界。
这类问题未必会被编译器直接判定为错误。如果测试用例没有覆盖到对应条件,也可能暂时发现不了。
C/C++ 静态分析的作用,就是在不实际运行程序的情况下检查代码,帮助开发者提前发现部分潜在缺陷和编码规则问题。
静态分析到底在分析什么?
根据 Parasoft 官方介绍,C/C++test 会结合模式匹配、控制流与数据流分析、抽象解释和代码度量等技术。名称看起来比较专业,其实可以简单理解为以下三种检查思路。
1. 检查代码中有没有已知的危险写法
这类似于用一套规则检查代码,例如:
是否使用了项目禁止的函数;
类型转换是否符合规范;
是否违反 MISRA、CERT、CWE 等相关检查规则。
这类检查适合帮助团队统一编码要求。但规则不是越多越好,如果一次启用大量与项目无关的规则,开发者可能会收到过多告警。
2. 顺着代码路径寻找问题
有些错误不是看一行代码就能发现的。
例如,一个指针在函数 A 中获得,在函数 B 中传递,最后在函数 C 中被使用。工具需要顺着代码的分支和调用关系,判断这个指针在使用时是否可能为空。
Parasoft 官方资料列出的相关问题包括空指针解引用、除零、内存泄漏、缓冲区溢出和污染数据流等。
3. 推测变量可能出现的状态
程序的输入情况非常多,不可能把所有情况都实际运行一遍。静态分析工具会推测变量可能出现的范围或状态。
例如,工具发现一个变量的可能取值包含 `0`,而它后面又被用作除数,就可以提示除零风险。
需要注意的是,静态分析可以帮助发现问题,但不能保证发现所有缺陷。结果还会受到代码完整性、构建配置、规则设置和工具版本等因素影响。
为什么要把检查放到 IDE 和 CI/CD 中?
如果只在项目发布前集中扫描,开发者可能一次收到大量问题。此时距离代码编写已经过去较长时间,需要重新理解当时的修改背景,处理起来会更困难。
Parasoft 官方资料说明,C/C++test 可以集成到 Eclipse、Visual Studio、VS Code 等开发环境,也可用于 CI/CD 流程。
比较容易理解的使用方式是:
比较容易理解的使用方式是:
- 开发者在 IDE 中修改代码
- 本地检查并处理明显问题
- 提交代码或创建合并请求
- CI/CD 使用统一规则再次检查
- 团队查看结果并持续处理问题
IDE 侧检查的重点是及时反馈,让开发者在还记得代码背景时处理问题。
CI/CD 侧检查的重点是统一标准,避免因为开发者本地配置不同或漏做检查,导致问题进入后续阶段。
两者并不是重复工作,而是分别解决“及时发现”和“统一执行”两个问题。
C/C++test 和 C/C++test CT 有什么侧重?
根据 Parasoft 官方产品介绍:
C/C++test 主要面向 IDE 集成,同时也支持命令行和 CI/CD 使用方式;
C/C++test CT 主要面向命令行与 CI/CD,也可结合开发者桌面环境和开源测试框架使用。
因此,选型时不能只看产品名称,还需要确认团队使用的 IDE、编译器、构建系统、测试框架和流水线,以及具体版本和授权包含哪些功能。
静态分析不能替代测试
静态分析很重要,但它只是软件质量流程中的一部分。
| 方法 | 主要用途 |
|---|---|
| 编译器告警 | 发现编译器能够识别的可疑写法和语言问题 |
| 静态分析 | 在不运行程序时分析部分代码路径、数据传播和规则问题 |
| 单元测试 | 检查函数或模块在给定输入下是否得到预期结果 |
| 运行时分析 | 观察程序实际运行时出现的内存或资源问题 |
| 人工评审 | 判断业务逻辑、设计意图和架构是否合理 |
例如,静态分析可能提示某条路径存在空指针风险,但它不能证明整个程序在真实硬件和所有运行环境下都正确。因此,静态分析不能替代单元测试、集成测试、系统测试和人工评审。
支持 MISRA 检查,不等于项目自动合规
Parasoft 官方资料列出了对 MISRA C/C++、AUTOSAR C++14、CERT C/C++、CWE、OWASP 等规则或标准的支持。
这些规则集可以帮助团队把部分编码要求变成自动检查,但“支持规则检查”不等于“使用工具后项目就自动合规”。
完整的合规工作通常还包括规则选择、偏离项审批、人工评审、测试验证、需求追溯和审计材料准备。具体认证与工具资格要求,也需要结合使用的产品版本、证书和项目流程确认。
存量项目如何开始使用?
已有大量代码的项目,第一次扫描时可能出现很多结果。比较稳妥的做法是分三步推进。
第一步:先确定最需要解决的问题
先判断项目更关注内存安全、编码规范还是网络安全,再选择相应规则,不要一开始就打开所有检查项。
第二步:优先控制新增问题
可以先为经过评审的历史结果建立基线,把检查重点放在新增和修改代码上。这样更容易明确责任和处理顺序。
基线不代表忽略历史问题,而是把治理工作分阶段进行。
第三步:小范围验证后再推广
先选择一个有代表性的模块,验证工具能否正确接入构建环境、告警是否有帮助、分析时间能否接受,以及团队如何处理误报和偏离项。
流程稳定后,再逐步扩大检查范围和门禁要求。
哪些团队更值得评估?
以下团队通常更适合进一步了解 Parasoft C/C++test:
开发嵌入式、安全关键或高可靠 C/C++ 软件;
需要执行 MISRA、CERT、CWE 或内部编码规则;
希望把代码检查接入 IDE 和 CI/CD;
需要将静态分析与单元测试、覆盖率或需求追溯结合;
存量代码较多,希望先控制新增问题,再逐步治理历史问题。
评估时,建议重点确认以下内容:
1. 是否支持项目使用的编译器、IDE、构建系统和目标平台?
2. 对项目关键代码的告警是否准确、有帮助?
3. 如何管理历史基线、误报告警和规则偏离?
4. IDE、CI/CD 和集中报告分别需要哪些产品组件与授权?
5. 如果项目涉及功能安全,当前版本有哪些适用证书和支持材料?
总结
C/C++ 静态分析前移,不是简单地增加一次代码扫描,而是让部分问题更早反馈给开发者。
Parasoft C/C++test 提供了多种静态分析方式,并支持在 IDE 与 CI/CD 场景中使用。IDE 适合及时反馈,CI/CD 适合执行统一规则,两者结合可以形成持续检查流程。
不过,工具能否真正发挥作用,还取决于规则选择、构建配置、历史基线和团队处理流程。静态分析应当与编译器告警、测试和人工评审配合使用,而不是替代它们。
本文依据 Parasoft 官方资料整理,产品功能、兼容性、认证范围和授权方式可能随版本调整,实际使用前应以对应版本的官方资料及合同约定为准。