项目第一次跑C-STAT的时候,结果列表里往往一下子就冒出很多警告,看着让人有点无从下手。面对这种情况,我们需要想清楚先处理哪些问题,筛选的时候又应该重点关注哪几种类型,不能只想着靠数量来清理,也不能机械地从列表最上面一条开始一条条去改。C-STAT这个工具会给每条检查出来的问题标上一个严重级别,分成High(高)、Medium(中)、Low(低)这三档,而且在结果窗口里面,我们可以设置让它只显示高级别的,或者只显示中等级别和高级别的。更实际的做法是,先把那些可能实实在在影响程序正常运行的风险给压下去,然后再腾出手来整理那些跟编码规范有关的问题,这样更容易踩稳节奏,不会乱。
一、IAR C-STAT检查结果太多该先处理什么
当C-STAT给出的结果数量比较多的时候,应该先挑那些可能会造成程序运行异常的问题去处理,然后再去看那些一般的规范性问题。这样做能避免团队把大量时间花在调整格式上,却不小心漏掉了真正会影响设备稳定性的代码。
1、优先查看严重级别最高的问题
做完分析以后,打开【C-STAT Messages】这个窗口,在【Severity】也就是严重程度的筛选选项里面,选择只显示【High】。把眼睛先盯在像数组访问超出了边界、对内存地址的不合法使用、空指针被直接拿来操作、用了没有初始化的变量、资源一直没释放干净,还有那些可能触发C语言里没有明确定义的行为这类问题上。C-STAT的检查说明文档里,对每条规则可能带来的后果都有着清楚的描述,比如会引起程序崩溃、行为变得没法预测,或者造成内存泄漏。
2、接着看附带了执行路径的那些警告
有一部分告警除了指出问题所在,还会额外给出Trace信息,也就是分析器在寻找问题的时候实际走过的那条执行路径。遇到那种分支判断特别多、函数一层套一层调得很深的问题,先顺着这条路径去看一看,比起只是盯着报错的那一行代码,更容易判断出这个风险到底是不是真实存在的。在C-STAT Messages窗口里面,对于部分检查出来的项目,是能够看到这一类路径信息的。
3、按照模块拆开来处理
最好不要让一个人硬着头皮去把一整个项目的所有告警都清理干净。可以试着先按驱动层、通信层、业务逻辑,还有那些公共组件,一块一块地拆开,然后把对应的部分交给负责那个模块的人去处理。那些被很多文件共同引用的公共头文件,常常会触发一大堆重复的告警,这种应该优先去修,因为只要把一个基础性的问题改掉,后面可能一下子就少掉一大批类似的结果。
4、把第三方的代码单独整理出来
供应商提供的库文件、工具自动生成的代码,还有以前留下来的历史模块,不要跟这次新写的代码混到一堆去处理。要是还想对它们保留检查,可以单独划出一个规则作用范围和一份整改的清单,免得第三方带来的问题把自研代码里藏着的风险给淹没掉,让人看不清楚。
二、IAR C-STAT问题筛选时优先看哪些类型
在筛选的时候,除了盯着那个严重程度的级别,还得结合检查项的具体名称、文件所处的位置,以及问题本身的类型来挑。IAR提供了一个叫作【Select C-STAT Checks】的窗口,在里面可以按规则包、规则组,甚至单独一条检查项去打开分析,也可以在里头看到每条检查项的严重级别和大致说明。
1、先挑内存和指针相关的问题来看
像数组边界越界、指针偏移出了问题、空指针和悬空指针,还有缓冲区的非法访问这类问题,通常都比一般的命名不规范和格式错误更值得先动手去改。嵌入式程序一旦访问了错误的地址,表现出来的现象往往是偶发性的复位、数据莫名其妙变掉,或者某个任务突然就跑飞了。
2、再优先去看初始化和控制流程方面的问题
变量没初始化就被用到、函数的返回值没有被检查、分支条件不小心漏掉了、存在永远不会被执行的死代码,以及条件判断的写法容易让人产生误解,这几样也应该尽早处理。这类问题有时候不会马上就报错,但在换了不同的编译优化选项、输入的数据不一样,或者程序跑在一些异常分支上的时候,它就可能一下子暴露出来。
3、利用规则名称来搜索
当结果窗口里列出来的条目实在太多的时候,可以在【Filter】过滤栏里面敲进检查项的名字或者关键词,这样就能把范围缩小很多。这个筛选功能是区分字母大小写的。另外,也可以在随便一条结果上面点右键,用【Copy Check Name】把这条检查的名字复制下来,再跑到C-STAT的设置里面,对着这条规则去查它的详细情况。
4、规范方面的问题安排分批去处理
跟MISRA、CERT和CWE这一类标准相关的要求,可以按照项目自己定下的规矩,一步一步地往后收敛。不要在第一轮就把所有的低风险告警一股脑都塞给开发人员。应该先确定哪些是强制必须遵守的规则,哪些是项目经过讨论同意豁免的,还有哪些是放到后面再去优化的,然后按照批次一波一波地去清理。
三、IAR C-STAT检查结果怎样避免反复积压
告警都清理完一遍以后,还得想办法让后面的分析能够一直保持在可控的状态里面,不然每次快要发布版本之前重新跑一遍,列表里面还是会堆满之前就已经见过的老问题。
1、先建好一个当前的基线
把那些已经确认过、眼下暂时不处理的遗留问题单独记录下来,写清楚为什么搁置、由谁来负责,以及后面打算怎么安排。新的代码提交的时候,重点去盯住新冒出来的High和Medium级别的问题,不能再让新问题继续滚进前面那份历史清单里面去了。
2、按文件来做小范围的复查
开发人员修改了代码之后,可以先单独选中这个文件,执行一下【C-STAT Static Analysis】→【Analyze File】。等到模块快要合并的时候,再去跑一下【Analyze Project】对整个项目做分析,这样既能减少每次等待的时间,也更容易判断新出来的告警到底是从哪一次改动里带进来的。
3、定期地把结果导出来
在C-STAT Messages窗口里头,可以用【Save to File】把当前的结果保存下来,或者生成一份HTML格式的报告。每次做版本评审的时候,就拿着这份报告,去比较一下High、Medium和Low这三个级别数量的变化,而不要只是简单地扫一眼告警的总数。
总结
当IAR C-STAT给出的检查结果数量太多的时候,先把严重级别为High的筛出来,再去处理那些附带了执行路径的、跟内存和指针、初始化以及控制流程相关的问题。在筛选的过程中,注意结合【Severity】选项、【Filter】过滤功能和检查项的名字来一点点缩小范围,而那些跟编码规范有关的告警,就按照项目定好的规则分批去清理。只要坚持把第三方代码、历史遗留问题和新增的问题分开来管理,C-STAT产生的结果才不会一直越积越多。