http://blog.chinaunix.net/uid-14833587-id-76561.html

在linux下并没有pclint,可以使用splint代替。
splint使用
一.splint介绍
splint是一个静态检查C语言程序安全弱点和编写错误的工具。splint会进行多种常规检查,包括未使 用的变量,类型不一致,使用未定义变量,无法执行的代码,忽略返回值,执行路径未返回,无限循环等错误。同 时通过在源码中添加注记给出的附加信息,使其可以进行功能更加强大的检查。而注记,则是对文件中的函数、变 量、参数以及类型进行假定的一种的程式化的注释。
二.splint的安装
下载地址:

http://www.splint.org/downloads/splint-3.1.2.src.tgz

文件: splint-3.1.2-src.tar.gz
大小: 2272KB
下载: 下载

源码包安装:
# tar zxvf splint-3.1.2.src.tgz
# cd splint-3.1.2
# mkdir /usr/local/splint
# ./configure --prefix=/usr/local/splint
# make install
# vi ~/.bashrc
添加:
export LARCH_PATH=/usr/local/splint/share/splint/lib
export LCLIMPORTDIR=/usr/local/splint/share/splint/import
# source ~/.bashrc
# export PATH=/usr/local/splint/bin/splint:$PATH

三.splint的使用
1.空引用错误

在引用没有指向任何内存地址的指针时,会导致这种错误.也就是使用了一个没有赋值的指针.
splint支持一种特别的注释.这种注释写在C程序代码中,用于对程序进行特殊说明.
如下面这段程序.使用了/*@null@*/进行了说明,表示说明*s的值可能会是NULL.

//null.c
char firstChar1 (/*@null@*/ char *s)
{
return *s;
}

char firstChar2 (/*@null@*/ char *s)
{
if (s ==NULL) return '\0';
return *s;
}
//END

使用splint扫描这个程序时,会输出:

# splint null.c
Splint 3.1.1 --- 28 Apr 2005
null.c: (in function firstChar1)
null.c:3:11: Dereference of possibly null pointer s: *s
null.c:1:35: Storage s may become null
Finished checking --- 1 code warning found
由于firstChar1和firstChar2都使用了null说明,表示指针s可能是个NULL值.
所以,splint会对s值的使用情况进行检查.因为firstChar2函数中,对s的值进行
了NULL的判断.所以,没有对firstChar2函数的指针s输出警告信息.

2.未定义的变量错误

C语言中,要求先定义变量,而后才可使用.所以,当使用一个没有定义的变量时,编译就会出错.
如下例,使用/*@in@*/说明的变量,表示必须进行定义.使用/*@out@*/说明的变量,表示在 执行过此函数后,这个变量就进行了定义.

// usedef.c
extern void setVal (/*@out@*/ int *x);
extern int getVal (/*@in@*/ int *x);
extern int mysteryVal (int *x);
int dumbfunc (/*@out@*/ int *x, int i)
{
if (i > 3) return *x;
else if (i > 1)
return getVal (x);
else if (i == 0)
return mysteryVal (x);
else
{
setVal (x);
return *x;
}
}
// END

使用splint检查usedef.c

$ splint usedef.c
Splint 3.1.1 --- 28 Apr 2005

usedef.c: (in function dumbfunc)
usedef.c:7:19: Value *x used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
usedef.c:9:18: Passed storage x not completely defined (*x is undefined):
getVal (x)
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
usedef.c:11:22: Passed storage x not completely defined (*x is undefined):
mysteryVal (x)

Finished checking --- 3 code warnings
//错误原因: 由于程序中没有对x进行定义,所以报未定义错误.但setVal()使用了/*@out@*/ 说明,所以
在setVal(x);和return x;中,没有报未定义错误.

3.类型错误

C语言中的数据类型较多,各个之间有些细微差别.splint也可以对变量类型进行检查.

示例1:

//bool.c
int f (int i, char *s,bool b1, bool b2)
{
if (i = 3) return b1;
if (!i || s) return i;
if (s) return 7;
if (b1 == b2)
return 3;
return 2;
}
//END

使用splint进行检查:

$ splint bool.c
Splint 3.1.1 --- 28 Apr 2005

bool.c: (in function f)
bool.c:4:5: Test expression for if is assignment expression: i = 3
The condition test is an assignment expression. Probably, you mean to use ==
instead of =. If an assignment is intended, add an extra parentheses nesting
(e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to
inhibit warning)
// 错误原因: if语句中的条件表达式是一个赋值语句.
bool.c:4:5: Test expression for if not boolean, type int: i = 3
Test expression type is not boolean or int. (Use -predboolint to inhibit
warning)
// 错误原因: if语句中的条件表达式的返回值,不是布尔型,而是整型.
bool.c:4:8: Return value type bool does not match declared type int: b1
Types are incompatible. (Use -type to inhibit warning)
// 错误原因: 返回值是布尔型,而不是整型.
bool.c:5:6: Operand of ! is non-boolean (int): !i
The operand of a boolean operator is not a boolean. Use +ptrnegate to allow !
to be used on pointers. (Use -boolops to inhibit warning)
// 错误原因: "!"操作符的操作数不是布尔型,而是整型i.
bool.c:5:11: Right operand of || is non-boolean (char *): !i || s
// 错误原因: "||"操作符的右操作数不是布尔型,而是字符指针.
bool.c:7:5: Use of == with boolean variables (risks inconsistency because of
multiple true values): b1 == b2
Two bool values are compared directly using a C primitive. This may produce
unexpected results since all non-zero values are considered true, so
different true values may not be equal. The file bool.h (included in
splint/lib) provides bool_equal for safe bool comparisons. (Use -boolcompare
to inhibit warning)
// 错误原因: 使用"=="对两个布尔型进行比较.应该使用"&&".

Finished checking --- 6 code warnings

示例2:

//malloc1.c
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
char *some_mem;
int size1=1048576;
some_mem=(char *)malloc(size1);
printf("Malloed 1M Memory!\n");
free(some_mem);
exit(EXIT_SUCCESS);
}

//END

使用splint检查malloc1.c

$ splint malloc1.c
Splint 3.1.1 --- 28 Apr 2005

malloc1.c: (in function main)
malloc1.c:9:25: Function malloc expects arg 1 to be size_t gets int: size1
To allow arbitrary integral types to match any integral type, use
+matchanyintegral.

Finished checking --- 1 code warning

修改变量size1的定义为:

size_t size1=1048576;

再使用splint进行检查.

$ splint malloc1.c
Splint 3.1.1 --- 28 Apr 2005

Finished checking --- no warnings

没有检查到错误.
4.内存检查

缓冲区溢出错误是一种非常危险的C语言错误,大部分安全漏洞都与它有关.splint可以
对缓冲区的使用进行检查.报告溢出或越界错误.
示例1:

//over.c
int main()
{
int buf[10];
buf[10] = 3;
retrun 0;
}
//END

使用splint进行检查

$ splint over.c +bounds +showconstraintlocation
Splint 3.1.1 --- 21 Apr 2006

Command Line: Setting +showconstraintlocation redundant with current value
over.c: (in function main)
over.c:6:3: Likely out-of-bounds store:
buf[10]
Unable to resolve constraint:
requires 9 >= 10
needed to satisfy precondition:
requires maxSet(buf @ over.c:6:3) >= 10
A memory write may write to an address beyond the allocated buffer. (Use
-likely-boundswrite to inhibit warning)

Finished checking --- 1 code warning

数组buf的大小是10字节.最大可使用的元素位置为buf[9],但程序中使用了buf[10].
所以报错.

示例2:

// bound.c
void updateEnv(char *str)
{
char *tmp;
tmp = getenv("MYENV");
if(tmp != NULL) strcpy(str,tmp);
}
void updateEnvSafe(char *str, size_t strSize)

{
char *tmp;
tmp = getenv("MYENV");
if(tmp != NULL)
{
strncpy(str, tmp, strSize -1);
str[strSize - 1] = '/0';
}
}
//END

$ splint bound.c +bounds +showconstraintlocation

Splint 3.1.1 --- 21 Apr 2006

Command Line: Setting +showconstraintlocation redundant with current value
bound.c: (in function updateEnv)
bound.c:6:19: Possible out-of-bounds store:
strcpy(str, tmp)
Unable to resolve constraint:
requires maxSet(str @ bound.c:6:26) >= maxRead(getenv("MYENV") @
bound.c:5:9)
needed to satisfy precondition:
requires maxSet(str @ bound.c:6:26) >= maxRead(tmp @ bound.c:6:30)
derived from strcpy precondition: requires maxSet(<parameter 1>) >=
maxRead(<parameter 2>)
A memory write may write to an address beyond the allocated buffer. (Use
-boundswrite to inhibit warning)
错误原因: 由于使用strcpy函数时,没有指定复制字符串的长度,所以可能导致缓冲区
溢出.后面的updateEnvSafe函数,使用了strncpy进行字符串复制,避免了这种情况.

到底需不需要编译器之外的独立的静态代码检查工具呢?这个问题'仁者见仁,智者见智'。但是有一个结论我想大 家都会认可,那就是越是在开发周期早期发现的Bug,修复它所付出的代价就越小。而像lint这样的静态代 码检查程序恰恰是让Bug在早期阶段'显露原型'的绝佳工具,而追求'lint- clean'[注1]境界的 代码也向来是专家级程序员的嗜好。别忘了在'C专家编程'一书中曾经提到Sun OS的内核一直是保持'lint-clean' 状态的,这就是榜样!还等什么?赶快学呀!^_^

有人抱怨'不敢用lint工具, 太多的Warnings把快屏幕都淹没了!',不过高手一般不这么想,他会细 心琢磨这些Warnings背后的'暗示',并和lint工具沟通,利用 lint工具提供的交互方 法屏蔽掉一些经过分析认为不能成为错误的Warnings。久而久之,高手本身就成了一个lint程序, 就能够很快的用肉眼发现代码中的问题,并指出问题所在,如何解决!他还能告知如何嵌入一些Annotations 从而避免让lint程序产生不必要的Warnings,这时这位高手对语言和程序的理解就又提高了一 个档次了。其实使用ling工具不仅仅是为了提早发现程序中的Bug,其使用过程有助于你加深对程序的认识 和理解。的确事实就是这样。

Splint就是一款强大而且应用广泛的开源lint工具。它的强大的代码检查能力固然让人称道,但是让我更 欣赏的却是它提供的'Annotations'机制。 Splint可以让程序员在自己的代码中嵌入相应的 Anotations,这些Anotations作为Splint分析代码时的输入以帮助Splint 产生对程序员更有用的信息。下面是一些Splint的使用入门,更多详细信息请查看'Splint manual'。

1、最简单的Splint使用方法
>> splint *.c

2、Splint输出Warnings的基本格式
<file>:<line>[,<column>]: message
[hint]
<file>:<line>,<column>: extra location information, if appropriate
我们可以使用'+/-<flags>'来自定义其输出格式,如'splint -showcol *c',则Splint不会在输出信息中显示'列'信息。

3、使用flags控制splint的检查范围和输出格式
'+<flag>' -- 表明某个flag处于打开状态,如'+unixlib';
'-<flag>' -- 表明某个flag处于关闭状态,如'-weak';

4、使用.splintrc环境文件
如果不想每次使用splint的时候都手工输入一堆'+/-<flags>',那么你可以把这些 '+/-<flags>'预先写到.splintrc文件中,当splint执行的时候它会自动加 上这些flags的。默认的flags设置在'~/splintrc'文件中,但是如果一旦splint的 当前工作路径下也有.splintrc文件,那么这个.splintrc文件中的flag设置会覆盖'~/splintrc'中 的 flags设置,但是命令行中的flags设置是具备最高优先级的,它会覆盖前面提到的任何一个文件中的flags 设置。

5、使用Annotations
对于'Annotations'的作用,Java程序员并不陌生,但是C程序员则对这个不是那么了解。C代码 中的Annotations用来指导Splint生成恰当的代码检查报告。下面这个例子对比使用和不使用Annotations,Splint 的输出的差别:
/* testlint.c */
void foo1() {
/*@unused@*/int *p = NULL;
}

void foo2() {
int *p = NULL;
}

splint testlint.c
Splint 3.1.1 --- 28 Apr 2003

testlint.c: (in function foo2)
testlint.c:6:7: Variable p declared but not used
A variable is declared but never used. Use /*@unused@*/ in front of
declaration to suppress message. (Use -varuse to inhibit warning)

Finished checking --- 1 code warning

可以看出没使用Annotation的函数foo2被给出Warning了。Splint的Annotations 繁多,我们在平时做lint时可以多多接触。

'早用lint,勤用lint',这是C专家给我们的建议。'lint-clean'也许离你并不遥远。

[注1]
'lint-clean' -- 程序能够顺利通过lint程序的检查。

splint
splint -I /usr/local/mysql/include/mysql/ +gnuextensions +trytorecover *.c

Splint C语言代码检测相关推荐

  1. ubuntu下c语言编程工具,Ubuntu系统下C语言代码检查工具(Splint)

    看一下下面的代码(当然包括错误,以检验splint的功能): #include int main(int argc,char* argv[]){ int a=100; /*没有使用的变量*/ int ...

  2. 恶意代码检测c语言,恶意代码检测分析软件

    恶意代码辅助分析工具最新版,这款就是刚被优化的代码检测软件,最大的用处的就是帮助你们检测自己电脑中的恶意代码,从而让你们一直拥有安全稳定的环境. 软件简介: 可以分析出系统里恶意代码的软件,免受电脑受 ...

  3. [网络安全提高篇] 一一五.Powershell恶意代码检测 (3)Token关键词自动提取

    "网络安全提高班"新的100篇文章即将开启,包括Web渗透.内网渗透.靶场搭建.CVE复现.攻击溯源.实战及CTF总结,它将更加聚焦,更加深入,也是作者的慢慢成长史.换专业确实挺难 ...

  4. 语言代码编程大赛简讯_精品干货:C语言的高效编程与代码优化

    在本篇文章中,我收集了很多经验和方法.应用这些经验和方法,可以帮助我们从执行速度和内存使用等方面来优化C语言代码. 简介 在最近的一个项目中,我们需要开发一个运行在移动设备上但不保证图像高质量的轻量级 ...

  5. 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码...

    浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...

  6. Linux系统中使用vim编写C语言代码实现过程

    博主这里是阿里云CentOs7的系统,以下涉及到的yum软件安装命令,在其他Linux发行版上可能会有些许不同,望读者安装时注意,如出现命令无法识别请根据对应发行版自行百度. 使用Linux进行C语言 ...

  7. 遥控汽车的编程c语言,智能小车循迹、避障、红外遥控C语言代码.docx

    //智能小车避障.循迹.红外遥控C语言代码 // 实现功能有超声波避障, 红外遥控智能小车, 红外传感器实现小车自动循迹, 1602 显示小 车的工作状态,另有三个独立按键分别控制三种状态的转换 // ...

  8. 循迹智能小车c语言主程序,智能小车循迹、避障、红外遥控C语言代码

    <智能小车循迹.避障.红外遥控C语言代码>由会员分享,可在线阅读,更多相关<智能小车循迹.避障.红外遥控C语言代码(13页珍藏版)>请在人人文库网上搜索. 1.智能小车避障.循 ...

  9. 网页301重定向检测工具(网页HTTP状态代码检测)

    301重定向是在搜索引擎优化中一个很常用的操作,可以帮助我们转移域名的权重.但是在做301重定向的时候由于服务器系统.网站程序语言.域名和链接地址的不同,使用的方法也不同.这个时候我们就要使用301重 ...

最新文章

  1. 二叉树的基本概念以及基本操作
  2. 艾媒报告丨2017年全球移动社交市场研究报告
  3. 【C++提高班】c++数组遍历比较相邻的数值
  4. 改变listview中item选中时文字的颜色
  5. C# WPF MVVM开发框架Caliburn.Micro IResult和协同程序⑥
  6. node.js 和 HTML5-Canvas 结合实现截图上传交互
  7. PyAutoIt 安装(Windows 版)
  8. 伴随矩阵,可逆矩阵相关思路分析之一
  9. STM32HAL库IIC驱动SH1108芯片OLED屏
  10. java游戏走到边缘_java-3D对象相遇的边缘和毛刺不均匀
  11. Android基于ViewPager2实现循环轮播图、3D画廊效果
  12. 2022年ps应该选择哪个版本
  13. 东哥带你们认清五险一金︿( ̄︶ ̄)︿
  14. 康考迪亚大学应用计算机科学,康考迪亚大学专业设置详情
  15. 【python】什么是序列,Python序列详解
  16. easyExcel导出excel文件并打包成zip压缩包下载
  17. Java SE菜鸟之异常
  18. Spring Boot SSL证书验证的问题
  19. 因签署Android独家协议排除竞争对手 谷歌在印度被罚款1.62亿美元
  20. 推荐几个值得关注的编程公众号

热门文章

  1. 浅析MVC、MVP、MVVM 架构
  2. mysql数据流图怎么做_数据流图的画法以及实例(精选)
  3. Docker再曝安全漏洞,这次是PWD的问题
  4. java 阿里云视频点播上传
  5. java 十进制转二进制代码_十进制转二进制代码
  6. Dynatrace系列之- 监控第三方API调用
  7. SQL Server查询本周、本年所有天数数据
  8. 多元文化研究---新加坡李光耀
  9. 网易智企首发:万字讲透元宇宙前世、今生与未来
  10. Type interface xxx.XxxMapper is not known to the MapperRegistry解决方案