☰
Polyspace 工具使用说明:从跑通到接入 CI 的工程实践
2026/10/13 11:43:31 网站建设 项目流程

简介:这份PDF文档面向嵌入式软件开发、测试验证及代码审核人员,系统讲解Polyspace静态检查工具的使用方法,帮助解决C/C++代码的鲁棒性问题,提升软件安全性与可靠性。内容涵盖工具基本介绍、工程建立流程、Bug Finder与Code Prover两大组件的分析配置,以及Output Summary、Dashboard、Result List、Source、Result Details等结果窗口的解读方式,并说明风险错误饼状图、覆盖度柱状图与代码颜色分级含义。资源包共1个PDF文件,约828KB,结构紧凑,适合作为随查随用的操作参考。目前已有2871人学习下载,读者可借此快速掌握从建工程、导入代码、选择分析模块到运行检查的完整链路,理解MISRA/JSF规则一致性检查、静态度量与测试覆盖度评估思路,并学会定位死代码、溢出等典型风险,为嵌入式项目的代码质量把关提供实用指引。

1. Polyspace 工具使用说明:从“跑通一次”到“敢放进 CI”的分水岭

很多团队第一次接触 Polyspace,都是被同一个场景逼出来的:嵌入式 C/C++ 代码在台架上跑得好好的,一上真实工况就出问题,回头查发现是某个除法没防零、某个数组越界踩了内存、某个int溢出绕过了判断。这类缺陷静态评审看不出来,动态测试又未必覆盖得到,于是有人提了一句“要不试试 Polyspace”。Polyspace 工具使用说明要解决的核心问题,就是把这些“运行时才炸”的隐患,在编译期用抽象解释的方式提前暴露出来。它适合谁?写车载、工控、医疗设备这类对可靠性有硬要求的 C/C++ 工程师,以及要把代码检查固化进流水线的构建负责人。这篇笔记不讲产品手册,只讲我实际把它跑起来、调准、接进流程的路径。

2. 先搞懂 Polyspace 在算什么:抽象解释与两类检查的分工

2.1 它为什么能在不运行代码的前提下报出溢出

Polyspace 的底层是抽象解释(abstract interpretation)。普通静态分析靠模式匹配,看到strcpy就报警;Polyspace 是把每个变量在所有可能执行路径上的取值范围算出来。比如一个int变量,它不记录具体值,而是记录一个区间[min, max],然后沿着控制流做区间运算。当某一步运算的结果区间超出了类型能表示的范围,它就报溢出;当数组下标区间超出了声明长度,它就报越界。

这带来两个直接后果。第一,它能做到“没有误报的漏报控制”——凡是它报出来的,理论上都存在一条真实可达的路径,这就是所谓 sound analysis(可靠分析)。第二,代价是它必须知道所有外部输入的边界,否则区间会无限扩张,最后满屏都是“可能溢出”。所以用 Polyspace 的第一件事不是点按钮,而是把输入约束交代清楚。

2.2 Bug Finder 和 Code Prover 到底该用哪个

Polyspace 有两个主要产品线,很多人一上来就混着用,结果报告看不懂。

维度Bug FinderCode Prover
分析目标找缺陷模式证明运行时安全
方法语义分析 + 模式匹配抽象解释,全路径
结果颜色单色(报/不报)绿/灰/橙/红四色
误报倾向有一定误报几乎无误报,但有“未证明”
典型用途编码规范、常见缺陷溢出、越界、除零、死代码
速度快慢,随复杂度上升明显

我的习惯是:日常提交用 Bug Finder 做快速门禁,版本节点或安全相关模块用 Code Prover 做深度验证。两者不是替代关系,是快慢两道闸。

2.3 四色结果的含义,决定了你怎么读报告

Code Prover 的结果颜色是它最容易被误读的地方,必须记牢:

  • 绿色:已证明该操作在所有路径下都安全。
  • 灰色:该代码不可达,或分析未覆盖到。
  • 橙色:存在一条路径可能出问题,但分析无法证明一定出问题(未证明)。
  • 红色:已证明存在一条可达路径一定出问题。

新手最常见的错误是把橙色当成误报直接忽略。橙色不是误报,是“我算不出来,需要你补约束”。你补的约束越准,橙色转绿或转红的比例越高,报告才越有参考价值。

3. 把第一个工程跑起来:从编译命令到结果面板

3.1 用 polyspace-configure 抓取真实编译命令

Polyspace 最怕的就是你手工填编译选项,漏一个-I或-D,分析结果就全歪。正确做法是让它在真实构建过程中抓取编译数据库。以常见的 Makefile 工程为例:

# 1. 先清理,保证编译命令完整被捕获 make clean # 2. 用 polyspace-configure 包裹原构建命令 # -output 指定生成的配置目录 polyspace-configure \ -output ./ps_config \ -compiler gcc \ -author my_name \ make all # 3. 检查抓取到的编译单元数量是否和工程一致 ls ./ps_config

逻辑说明:polyspace-configure本质是一个编译器包装器,它拦截每一次gcc调用,把真实的宏定义、头文件路径、优化等级记录下来,生成一份 Polyspace 能直接消费的工程配置。参数上,-compiler要和你实际用的编译器一致,否则内建类型宽度可能对不上;-output目录里会生成每个源文件对应的.psprj配置。跑完一定要核对编译单元数量,如果比实际少,说明有些文件没被 Makefile 触发编译,需要单独补。

3.2 命令行启动一次 Code Prover 分析

有了配置目录,就可以用命令行跑分析,这样后面接 CI 才顺:

polyspace-code-prover \ -project ./ps_config/my_project.psprj \ -results-dir ./ps_results \ -target x86_64 \ -sources main.c driver.c sensor.c \ -include ./inc \ -define "DEBUG=0" \ -prover-options "-O2"

逻辑说明:-project指向抓取到的工程文件;-results-dir是结果输出目录,后续用polyspace-results-export导出;-target决定指针宽度和字节序,嵌入式交叉编译场景必须换成目标架构,比如arm或powerpc,这一步错了后面所有内存相关结论都不可信;-define用来对齐构建时的宏,尤其是那些控制条件编译的开关,漏了会导致分析的分支和实际固件不一致。

3.3 在结果面板里按“红→橙→灰”的顺序清理

分析跑完,打开结果界面,不要从头往下逐条看。我的顺序是:

  1. 先看红色。红色是确定缺陷,逐条确认是否真实可达,是就改代码,不是就说明约束给错了。
  2. 再看橙色。橙色集中在哪几个变量、哪几个函数,通常是输入边界没交代清楚,回到3.1补-define或加assert约束。
  3. 最后看灰色。灰色大量出现往往意味着有整块代码没被分析到,检查是不是有文件没进-sources。

提示:第一次分析橙色占比很高是正常的,不要因此否定工具。把橙色当成“待补的输入约束清单”,一轮轮收敛,通常三轮之内能压到可接受范围。

4. 让结果可信:约束、精度与性能的三角平衡

4.1 用 assert 和边界标注把橙色逼成绿色

Polyspace 不知道你的传感器读数范围,它只能假设int全域。你告诉它“这个值只可能是 0 到 1023”,它就能把大量橙色判成绿色。手段有两种,一种是在代码里加运行时断言:

#include <assert.h> int read_adc(void) { int raw = hw_read(); /* 告诉 Polyspace:硬件保证返回值在 0..1023 */ assert(raw >= 0 && raw <= 1023); return raw; }

逻辑说明:assert在 Polyspace 眼里是一条路径约束,它会把raw的区间收窄到[0,1023],后续所有基于raw的运算精度都会提升。注意这些断言在发布版本里通常被NDEBUG关掉,所以它不影响运行时行为,只服务于分析。另一种手段是用 Polyspace 提供的PS_系列标注宏,适合那些无法用普通断言表达的范围约束。

4.2 精度等级调高,分析时间会怎么变

Code Prover 有精度相关的选项,调高会显著增加分析时间。经验数据是:默认精度下,十万行级工程单次分析在几十分钟量级;把路径敏感度和循环展开调高,时间可能翻三到五倍。所以不要一上来就拉满。

选项方向效果代价
提高循环展开次数减少循环导致的橙色时间线性上升
开启路径敏感分支判断更准内存占用明显上升
收窄输入区间橙色大幅下降需要人工补约束
提高并发线程数缩短墙钟时间吃机器核数和内存

我的做法是:日常门禁用默认精度,只卡红色;版本发布前用高精度跑一次全量,人工过橙色。

4.3 大工程怎么切分才跑得动

几十万行的工程一次性分析,内存和时间都扛不住。常见做法是按模块切分,每个模块单独建工程,共享同一份头文件约束。切分边界选在接口清晰、耦合低的地方,比如驱动层和应用层之间。切完之后,跨模块的调用用桩函数(stub)替代,桩函数里把输入输出范围写清楚,这样既控制了单次分析规模,又不会因为桩函数太随意而丢掉真实约束。

5. 避坑与排查:那些让报告失真的常见问题

5.1 分析结果和实际固件对不上

现象:Polyspace 报某处不会溢出,但实机跑出来溢出了。原因:-target或-define和真实构建不一致,导致类型宽度或条件编译分支不同。解决:用polyspace-configure重新抓取,逐项比对宏定义列表,尤其是那些在 Makefile 里动态拼接的-D。

5.2 橙色结果铺满整个报告

现象:几乎每个变量运算都是橙色。原因:某个全局输入没有边界约束,区间一路扩张污染了整条数据流。解决:从橙色最集中的函数往上追,找到那个“源头变量”,补assert或标注。通常一个源头能消掉一大片橙色。

5.3 分析跑了一半内存爆掉

现象:分析进程被系统杀掉。原因:路径敏感选项开太高,或者单个编译单元过大。解决:先降精度选项,再把超大源文件按功能拆分,或者用-max-processes控制并发,避免多个分析进程同时抢内存。

5.4 灰色代码里藏着真实缺陷

现象:某段代码显示灰色不可达,但实际会被执行。原因:前面的条件判断被 Polyspace 判定为恒假,通常是某个宏定义给错了。解决:检查该分支依赖的宏,确认分析配置和构建配置一致。灰色不等于安全,它只表示“没分析到”。

5.5 把 Bug Finder 的告警当 Code Prover 结论用

现象:拿 Bug Finder 的单色报告去证明“代码无溢出”。原因:两者分析目标不同,Bug Finder 不做全路径区间运算。解决:安全相关的结论必须来自 Code Prover,Bug Finder 只用于快速筛查编码类缺陷。

6. 接进流水线:让 Polyspace 从“偶尔跑”变成“每次跑”

6.1 用退出码做门禁,而不是靠人看报告

命令行分析支持通过选项控制退出码,把“有红色就失败”变成流水线的一步:

polyspace-code-prover \ -project ./ps_config/my_project.psprj \ -results-dir ./ps_results \ -checkers-severity-high error \ -exit-status-level error # 退出码非 0 即代表存在高严重度缺陷,流水线据此中断 echo "exit code: $?"

逻辑说明:-checkers-severity-high把高严重度检查项的处置级别设为error,-exit-status-level决定什么级别会让进程返回非零。这样构建脚本不需要解析报告文本,只看退出码即可。参数上要注意,级别设太严会导致大量橙色也中断流水线,初期建议只卡红色,稳定后再逐步收紧。

6.2 结果导出与趋势跟踪

单次报告意义有限,趋势才有价值。用导出命令把结果转成可入库的格式:

polyspace-results-export \ -results-dir ./ps_results \ -format csv \ -output ./ps_results/report.csv

逻辑说明:-format支持 csv、xml 等,csv 方便导入表格做趋势图。把每次流水线的红色数、橙色数记下来,画成曲线,能直观看出代码质量是在收敛还是在恶化。这一步是很多团队漏掉的,结果就是工具跑了但没人看,形同虚设。

6.3 一个我踩过的坑:别在第一天就卡全量

我早期接手一个项目时,图省事直接把全量 Code Prover 设成每次提交必跑、红色橙色一律中断。结果第一天流水线就没绿过,团队怨声载道,两周后大家集体要求关掉。后来改成:提交时只跑改动模块的 Bug Finder,每日夜间跑全量 Code Prover 且只卡红色,橙色进周报人工评审。节奏对了,工具才留得下来。Polyspace 这类可靠分析工具,价值不在一次跑出多少告警,而在能不能长期稳定地跑下去。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询