下面这些例子说明FlexeLint/PC-lint的一些功能。通过修改这些代码样本,可以分析它们的原因和处理结果。
“Off-By-One”错误实例(C源码)
下面的例子说明了FlexeLint/PC-lint为什么会出现“Off-By-One”错误。
/* Off-By-One Example */
#include
int main()
{
int i;
int a[] = {1,2,3};
int n = sizeof(a)/sizeof(int);
for(i=0;i<=n;i++)
printf("a[%d]=%d\n",i,a[i]);
return 0;
}
“Multi-pass”实例(C源码)
这个实例说明了FlexeLint/PC-lint's分析后的伪执行能力。注意使用嵌入的lint选项。
//lint -passes(4)
int f( int n )
{
return 10/n;
}
int g( int n )
{
if( n == -1 ) return 0;
return f(n) + g( n - 1 );
}
int main()
{
return g( 3 );
}
基于规则的语法(C源码)
这个例子说明了FlexeLint/PC-lint是怎样进行语法检查的。
下面的例子演示了如何使用语义选项。
lint -sem( fill, 1p >= N ) :“fill” 的含义是指向一个长度至少为N的区域。
lint -sem( copy, @p == 1p ): “copy”的返回值指向一个大小(“copy“的第一个参数值)等于该区域的区域
注释:
"1p" 是一个区域的长度,由给定函数的第一个参数指定。
"@p" 是一个区域的长度,由给定函数的返回值指定。
#include
#include
void fill( char * );
char *copy( char * );
#define N 100
基于规则的语法(C++源码)
这个例子说明了一个简单的C++程序是如何出现错误的。
#include
class X
{
int *p;
public:
X()
{ p = new int[20]; }
void init()
{ memset( p, 20, 'a' ); }
~X()
{ delete p; }
};
Strong typedef检查实例(C++源码)
这个例子说明了FlexeLint/PC-lint是怎样检查Strong typedef用法的。
Strong typedef,可以使FlexeLint可以在不匹配的情况下给报告分配标称。下面是函数combine()中的错误报告。之后的选项将赋予它们三个强大的stypedef名(之后会定义它们) ,并具有AcJcX的特性。它们的含义是报告分别在分配冲突给typedef时 (但不包括c-onstants),加入typedef时 (但不包括constants) 和从typedef中提取。
lint -strong( AcJcX, Length, H_Position, V_Position )
#define Max(x,y) ((x) >= (y) ? (x) : (y))
#define Min(x,y) ((x) >= (y) ? (y) : (x))
以下三种typedef
// types
typedef int Length;
typedef Length H_Position;
typedef Length V_Position; struct Point
{
H_Position x; // horizontal position
V_Position y; // vertical position
};
struct Rectangle
{
Point ul; // upper left boundary
Point lr; // lower right boundary
};
下面的函数计算没有complaint。长度使用H_Position和V_Position的通用形式定义。
Length perimeter( const Rectangle &r )
{
Length len = 0;
len += 2 * (r.ul.y - r.lr.y); // combining V_Position with Length
len += 2 * (r.lr.x - r.ul.x); // combining H_Position with Length
return len;
}
下面的函数绘制了一些合理的complaints。在这个函数中,需要H_Position和V_Position两种类型。它们被视为不能合并的,单独不同的类型。当这种情况出现的时候,就会发出警告。
combine(r1,r2) :形成一个刚好覆盖r1和r2的大矩阵。
Rectangle combine( const Rectangle &r1, const Rectangle &r2 )
{
Rectangle r;
r.ul.x = Min( r1.ul.x, r2.ul.x ); // OK
r.ul.y = Max( r1.ul.y, r2.ul.y ); // OK
r.lr.x = Max( r1.lr.y, r2.lr.x ); // Complain
r.lr.y = Min( r1.lr.x, r2.lr.x ); // Complain
return r;
}
引入多个模块
这个例子介绍了FlexeLint/PC-lint如何跨模块分析 。
当多个模块(即单独的编译单元)呈递给FlexeLint时,将被当做同一应用的部分来处理。FlexeLint的跨模块功能使它拥有编译人员不具备的透视功能。 然而,早期的版本中限制使用者只能同时编辑和提交一个文本。所以那时,编程人员没有办法在线测试多个模块。这就导致了很多人没有办法在多模块中写出有意义的报告。
一个.mm文件应该包含如下形式:
第一行评论
第二行评论
……
第N行评论
第一个模块名
……
最后一个模块名
第一个标题名
……
最后一个标题名
所有的'@'指令必须从第1列开始。注释行是可选的。 实际的C或C ++源代码可选择定义。没有必要把标题放在每个模块的后面。它们可以自由穿插。此外,空白行可以在整个文中中穿插。 模块可以有 .c 或 .cpp扩展或两者的混合。
如下例:
@module c1.cpp
#include "c.h"
int f()
{
return g(0) + 2;
}
@module c2.cpp
#include "c.h"
int g( int *p )
{
return ++*p;
}
@header c.h
int g( int * );
多模块的初始化和冗余
这个例子说明FlexeLint/PC-lint如何进行跨模块初始化顺序问题的检测。
本实例说明初始化中a.cpp的a变量和b.cpp的b变量的检测。还说明了对ab.h中未使用元素的检测。 随着时间的推移可以聚集不再使用的元素。注意区别对待stdio.h和 ab.h。 stdio.h在应用中有许多没有使用的声明,但这些没有被说明。ab.h中未被使用的声明会报告出来。
@module a.cpp
#include
#include "ab.h"
int a = f();
int main()
{
printf( "b is %d\n", b );
return 0;
}
@module b.cpp
#include "ab.h"
int b = a;
int f()
{
return 3;
}
@header ab.h
extern int f(void);
extern int a;
extern int b;
typedef int INT32;
#define ReturnValue 3
struct A { int a, b; };
FlexeLint/PC-lint最新下载地址