静态分析常见问题
静态分析也是codereview重要环节,越是成熟的企业,越是对这些细节关注或投入巨大精力(其实都是伤害过才知道)
C++这个双刃剑,需要更小心翼翼才可以不被伤到
静态分析工具,可以使用C++ Test也可以使用轻量的CppCheck,
个人觉得还是根据实际来进行,比如,真的很重视代码质量,建议用C++ Test,毕竟比较专业,能检查的东西也比较多
如果仅仅自己使用,比如说重视下自己的代码,可以用Cppcheck,其实cppcheck很不错了,还可以支持自己开发
前面写过关于CppCheck的一些常见问题,今天整理下C++Test一些常见问题:
1. 参数在使用之前未被初始化
其实标题已经非常明确了,也很好理解。理论上来说,这种低级错误,我们应该不会怎么犯规的。
但实际并非如此,主要是什么原因?
换个角度来说,如果真的拿了一个未初始化的值进行运算,表现出来的现象就是很奇怪的,甚至每次效果还不一样,
给确定问题带来极大的困难,我觉得,对于静态检查,这个是必不可少的。
举个例子:(实际项目哦)
首先,C++Test是这样报错的:
看下实际报错的位置代码:
经过分析,ALCOMM_SendData对第一个参数是没有判断的,因此,实际运行是不存在问题的。
这个也比较容易忽视潜在风险,比如说后期,我们改进了 ALCOMM_SendData 函数,增加对第一个参数的判断,那就尴尬了
类似问题,还存在以下情况:
这样的代码相对来说更隐秘一点,
申明的时候,未进行初始化。if条件符合的时候,是有赋值操作,但else是没有做任何处理
假设,存在else的情况时候,此时返回的是野指针(影响就大了)
这种代码正因为没有暴露出问题,主要是实际场景是不会进入else条件
再来一例:
这些都是要好好想想,怎么改进才好。
改进的办法,往往很简单,比如说给个初始值。
但这样改就合适吗?
显然不合理,既然初始值给一个就可以,那给多少?0还是-1,都不一样么,说不定反而不正确的
还有,以前没有初始值的时候,为什么功能看起来也都正常?
是啊,这些都是拦路虎,不揪细节,是不能说服自己的。
比如说:表示月份的数据,如果给个0,则意味着0月份,实际是不对的,因为不存在0月份这样说法
xx 总是评估为True 或 False
这也是一种极其常见的错误方法。
这个也非常烧脑,如果仅仅是简单的倒好
数组越界的风险。
报错的现象:
stLimitCurve是个数组,总共120个,但实际使用的时候,没有对byLimitCurveLength进行限制判断,从而导致存在越界的风险。
但实际代码,的确也会有判断,例如:
此时,可能会导致人员分析不到位的情况,需要进一步分析
实际结果:提示的地方,不在if判断里面!!!
改进方式:
增加有效性判断或将有效性判断范围扩大覆盖全部的指令。
进一步改进:在else 地方增加错误日志记录
空指针的风险
-
- 这个比较好理解,就是说pData可能是空指针
- 这里要分两种情况:
- pData是传入参数
-
-
- 指针是某个函数的返回值
-
-
- 针对第1种情况,增加if的判断一般是可以的。但要进行代码分析,这个if语句加在函数入口是否合理?还是仅仅是用到之前加判断。这个也不一样。
- 针对第2种情况,还是先分析调用函数的代码。是否存在返回null的情况,即便不存在返回null的情况,在使用之前也要加if判断
其他非违规的建议改进
- 当case 最后一个条件与default处理是一致时,通过移除break的方式实现的。
- 建议改进:case必须与default分开,即便处理是一致的。
- 在default分支里增加错误日志输出
- 当case分支里,有条件进入下一个分支(不是通过状态机,下一个执行进入)。
- 此时就是if,建议直接用if else好了,不需要switch case
- bool 类型要使用程序定义的,即bool_t。 这里要说下,主控板这边bool_t是uint8_t类型,通信记录板bool_t是uint32_t类型,不一样。uint8_t类型,也有点问题,比如说,我们定义TRUE是这样的:#define SF_TRUE 0xA5u
#define是四个字节的,那么每次 bool_t bIsTest = SF_TRUE; 都会存在类型强制转换的操作,也是不好的做法
- 使用EQ替代==,NOT_EQ替代 !=