嵌入式Cppcheck静态分析代码质量CI/CD
前言
仪表类产品(BMS、DTU、传感器、PLC、工业控制器)代码出错代价极高。传统开发依赖人工review和测试,覆盖率低。
Cppcheck 是一款免费、开源、无需编译的静态分析工具,特别适合资源受限的仪表嵌入式团队。
一、Cppcheck 核心能力
| 检查类型 | 嵌入式场景 | 严重程度 |
|---|---|---|
| 空指针解引用 | 指针操作前未判空 | 🔴 高 |
| 内存泄漏 | malloc未free | 🔴 高 |
| 数组越界 | 传感器数据缓冲溢出 | 🔴 高 |
| 野指针 | 指针释放后继续使用 | 🔴 高 |
| 整数溢出 | 计数器溢出 | 🟡 中 |
| 逻辑错误 | if (x = y) 写成赋值 | 🟡 中 |
| 死代码 | 永不会执行的分支 | 🟢 低 |
二、四大典型应用场景
场景1:传感器数据处理
数组越界和空指针是最常见问题:
// Cppcheck 会报警:Array accessed at index 5, which is out of bounds.
int16_t* pData = g_sensor_buf[channel];
if (pData != NULL) { process_data(pData); }
场景2:通信协议解析
Modbus、DL/T645、HJT212 等协议解析时,边界检查是重灾区:
// Cppcheck 会报警:Buffer access out-of-bounds
uint8_t count = frame[5];
for (int i = 0; i < count; i++) {
registers[i] = (frame[6+i*2] << 8) | frame[7+i*2];
}
场景3:定时器/中断处理
volatile 共享变量访问的原子性问题:
volatile uint32_t g_tick_count = 0;
// Cppcheck 报警:volatile 变量需要原子操作
void TIM2_IRQHandler(void) { g_tick_count++; }
场景4:EEPROM 参数存储
掉电保存配置时未验证数据有效性:
// Cppcheck 报警:Buffer overflow,channel_count 未验证可能超限
DeviceConfig_t* cfg = (DeviceConfig_t*)eeprom_data;
g_thresholds[i] = cfg->thresholds[i]; // 越界访问
三、安装与基本使用
# Ubuntu 安装
sudo apt-get install -y cppcheck
cppcheck --version
# 扫描整个目录
cppcheck --enable=warning --std=c11 --platform=unix32 App/ Drivers/
# 输出报告
cppcheck --enable=all --std=c11 --output-file=cppcheck-report.txt App/
四、推荐参数组合(仪表嵌入式)
cppcheck \
--enable=warning,performance,portability \
--std=c11 \
--platform=unix32 \
--force \
--inline-suppr \
--verbose \
--suppress=unusedFunction \
App/ Drivers/ Core/Src/
五、GitHub Actions CI/CD 集成
name: Cppcheck Static Analysis
on: [push, pull_request]
jobs:
cppcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Cppcheck
run: sudo apt-get install -y cppcheck
- name: Run Cppcheck
run: |
cppcheck --enable=warning,performance,portability \
--std=c11 --platform=unix32 --force \
--output-file=cppcheck-report.txt \
App/ Drivers/ 2>&1 || true
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: cppcheck-report
path: cppcheck-report.txt
六、Makefile 集成
cppcheck:
cppcheck --enable=warning,performance,portability \
--std=c11 --platform=unix32 --force \
--output-file=cppcheck-report.txt \
App/ Drivers/ 2>&1 || true
make cppcheck # 本地一键检查
七、误报处理:STM32 HAL 库 stub
// stub.h - 抑制 HAL 库相关误报
#ifndef __CPPCHECK_STUB_H__
#define __CPPCHECK_STUB_H__
#define HAL_GPIO_WritePin(a,b,c) ((void)0)
#define HAL_Delay(a) ((void)0)
#endif
cppcheck --std=c11 --include=stub.h App/
八、落地路径(4天)
| 天数 | 内容 |
|---|---|
| 第1天 | 安装 cppcheck,扫描 App/,统计问题数 |
| 第2天 | 分析分类,加 suppress 抑制误报 |
| 第3天 | 集成 GitHub Actions CI |
| 第4天 | Makefile 集成,make cppcheck |
九、局限性
- ❌ 查不出业务逻辑错误(如上限下限写反)
- ❌ 嵌入式寄存器操作(HAL封装后看不到)
- ❌ 实时性问题(死锁、中断优先级反转)
- ✅ 定位:代码审查的辅助工具,不是替代品
参考资源
| 资源 | 链接 |
|---|---|
| Cppcheck 官网 | https://cppcheck.sourceforge.io/ |
| Cppcheck 手册 | https://cppcheck.sourceforge.io/manual.pdf |
本文档由 Leonard(QA测试工程师)编写 | 2026-04-16