[toc]
一、安装
1、在网络环境、配置OK的系统,可以 yum 一键安装
2、某些情况无法一键安装,需要下载源码自己安装
下载splint-3.1.2.tar.gz:https://github.com/splintchecker/splint
3、安装
[wishcell@localhost]~/test/splint-master% autoreconf -vif
[wishcell@localhost]~/test/splint-master% ./configure
[wishcell@localhost]~/test/splint-master% make
....
e.o lclsyntable.o lcltokentable.o sort.o symtable.o lclinit.o shift.o lclscan.o lsymbol.o mapping.o -lfl
/usr/bin/ld: 找不到 -lfl
collect2: 错误:ld 返回 1
make[3]: *** [splint] 错误 1
make[3]: 离开目录“/home/wishcell/test/splint-master/src”
make[2]: *** [all] 错误 2
make[2]: 离开目录“/home/wishcell/test/splint-master/src”
make[1]: *** [all-recursive] 错误 1
make[1]: 离开目录“/home/wishcell/test/splint-master”
make: *** [all] 错误 2
[wishcell@localhost]~/test/splint-master%
解决 -lfl 报错问题:
[root@localhost splint-master]# sudo yum install flex
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
正在解决依赖关系
--> 正在检查事务
---> 软件包 flex.x86_64.0.2.5.37-3.el7 将被 升级
---> 软件包 flex.x86_64.0.2.5.37-6.el7 将被 更新
--> 解决依赖关系完成
然后重新: ./configure && make 时间还挺长,最后仍然报错,还是找不到
原来需要安装开发包:
[root@localhost splint-master]# yum -y install flex-devel
再次 make ,很快完成
[root@localhost splint-master]# whereis splint
splint: /usr/local/bin/splint
[root@localhost splint-master]#
二、linux下面,超级严格的代码检查工具
1、基础用法,检验单个文件
A、示例代码
test.c:
int main()
{
int a = 3;
int b = 4;
printf("a +b = %d", a +b);
return 0;
}
B、用法
/usr/local/bin/splint test.c
2、检测工程,需要对复杂的目录结构下所有C文件检测
A、困难
此时,检测的每个C文件,都会要求包含其依赖的头文件。
即需要包含头文件。项目特别复杂,怎么办?
B、解决办法
可以信托项目中原来的 makefile 框架,在编译规则中,将生成
中间文件 .o 的操作,改为splint检测规则
C、举例
GTEST_DIR=./GTEST-1.7.0
CurrDir=$(shell pwd)
spline=/usr/bin/splint \
-booltrue TRUE \
-retvalint \
+bounds \
-type \
+boundsread \
+trytorecover \
-nullstate \
charindex \
-immediatetrans\
-mustfreefresh \
-nullret \
mustfreeonly \
-temptrans \
-dependenttrans\
-boundswrite \
-bufferoverflowhigh \
-retvalother \
-mayaliasunique\
-exportlocal \
-initalelements\
+ignoresigns \
+ignorequals \
+relaxtypes \
-predboolothres\
-predboolint \
-globstate \
-unqualifiedtrans\
-compdestroy \
-compdef \
-usedef \
-paramuse \
-nullassign \
-formattype \
-onlytrans \
-nullpass \
-usereleased \
-redef \
-compmempass \
-branchstate \
+posixlib \
-shiftnegative \
-boolops \
-evalorder \
-unregcog \
-likelybool
PrjDir = ../
Module1= ../module_1/source
Module2= ../module_2/source
Module3= ../module_3/source
CaseDir = ./case
stubDir = ./stub/source
linux_env=$(shell getconf LONG_BIT)
ifeq($(linux_env), 32)
DEFS=-DMACHINE_BIT32=32
else
DEFS=-DMACHINE_BIT64=64
endif
INCS=-I../module_1/include \
-I../module_2/include \
-I../module_3/include \
-I$(GTEST_DIR)/include\
-I$(GTEST_DIR)/include/gtest \
-I$(GTEST_DIR)/include/gtest/internal
vpath %c $(../module_1)
vpath %c $(../module_2)
vpath %c $(../module_3)
PrjSrc=$(notdir $(wildcard $(module1_dir)/*.c))\
$(notdir $(wildcard $(module2_dir)/*.c))\
$(notdir $(wildcard $(module3_dir)/*.c))
PrjOBJ=$(PrjSrc:%.c=$(PrjOBJDir%.x))
stubOBJ=$(stubSrc:%.c=$(StubOBJDir%.x))
#这里原来是做中间文件生成的,但是现在让它生成检测日志
$(PrjOBJDir)%.x : %.c
@$(SPLINT) ${INCS} $< || echo ''
$(TESTS): ${PrjObj} ${CaseObj} ${StubObj}
echo ''
.PHONY: clean
clean:
rm -f $(TESTS) *o *.gcda *
三、强大的测试能力
1、典型示例
A、典型案例背景说明
对数据非法越界操作,连valgrind都无法检测,甚至一个warning都没有.
在splint的检测报告中,显然看到了对它的告警
B、示例代码
混用结构体中的 char data[0]; 和 char *data 成员。
造成特定类型cpu环境崩溃。在某些环境上,无异常症状
C、实例检测效果
i、先用 valgrind 做对比实验
valgrind --tool=memcheck -leak-check=full --max-stackframe=20000000 ./xx > log 2>&1
ii、splint 检测结果
在修改 splint 告警的过程中,必然会解决掉越界问题