1. PC-Lint工具介绍
PC-Lint for C/C++是由Gimpel软件公司于1985年开发的代码静态分析工具,它能有效地发现程序语法错误、潜在的错误隐患、不合理的编程习惯等。
C语言的灵活性带来了代码效率的提升,但相应带来了代码编写的随意性,另外C编译器不进行强制类型检查,也带来了代码编写的隐患。PC-Lint能识别并报告C语言中的编程陷阱和格式缺陷的发生。它进行程序的全局分析,能识别没有被适当检验的数组下标,报告未被初始化的变量,警告使用空指针,冗余的代码,等等。软件除错是软件项目开发成本和延误的主要因素。PC-lint能够帮你在程序动态测试之前发现编码错误,这样消除错误的成本更低。使用PC-Lint在代码走读和单元测试之前进行检查,可以提前发现程序隐藏错误,提高代码质量,节省测试时间。并提供编码规则检查,规范软件人员的编码行为。
PC-Lint能够检查出很多语法错误和语法上正确的逻辑错误,PC-Lint为大部分错误消息都分配了一个错误号,编号小于1000的错误号是分配给C语言的,编号大于1000的错误号则用来说明C++的错误消息。表 1 列出了PC-Lint告警消息的详细分类:详细信息可参考c:/lint/msg.txt 文件
C C++ Warning Level
Syntax Errors 1 - 199 1001 - 1199 1
Internal Errors 200 - 299 1200 - 1299 0
Fatal Errors 300 - 399 0
Warnings 400 - 699 1400 - 1699 2
Informational 700 - 899 1700 - 1899 3
Elective Notes 900 - 999 1900 - 1999 4
以C语言为例,其中的编号1-199指的是一般编译器也会产生的语法错误;编号200-299是PC-Lint程序内部的错误,这类错误不会出现在代码中的;编号300-399指的是由于内存限制等导致的系统致命错误。编号400-999中出现的提示信息,是根据隐藏代码问题的可能性进行分类的:其中编号400-699指的是被检查代码中很可能存在问题而产生的告警信息;编号700-899中出现的信息,产生错误的可能性相比告警信息来说级别要低,但仍然可能是因为代码问题导致的问题。编号900-999是可选信息,他们不会被默认检查,除非你在选项中指定检查他们。
2. 安装
pclint不是免费的哦。不过也不贵,我们公司好像只花了2K大洋吧。运行安装文件pclint9后就可以很简单地安装了。
版本
Q:如何查看版本?
A:见readme.txt:
PC-lint for C/C++ Version 9.00e
3. 开始使用
3.1. 不用任何配置,直接使用
3.1.1. 准备待被检查的文件:
先在E:/建一个文件:main.cpp,内容为:
void main() { } |
3.1.2. 最简单的用法
在命令行下输入:D:/>C:/lint/lint-nt E:/main.cpp
C:/lint>C:/lint/lint-nt E:/main.cpp PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: E:/main.cpp _ } E:/main.cpp 3 Info 783: Line does not end with new-line C:/lint> |
PCLINT已经工作了,是不是简单的难以让人相信。
3.1.3. 最简单的标准用法
修改被检查的文件E:/main.cpp,内容修改为:
#include <stdio.h> void main() { printf("hello pclint/n"); } |
再次在命令行下输入:D:/>C:/lint/lint-nt E:/main.cpp
D:/>lint PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: E:/main.cpp _ #include <stdio.h> E:/main.cpp 1 Error 322: Unable to open include file 'stdio.h' D:/> |
报错误,“不能找到头文件stdio.h”
当然PCLINT不可能也不应该知道到哪里去找stdio.h,stdio.h所在的路径需要我们告诉它。
如何告诉呢?
通常的做法是在xxx.lnt文件中指定,然后指定使用这个xxx.lnt文件。
最简单的是使用 c:/lint/std.lnt 这个文件。
3.2. std.lnt的配置:
3.2.1. std.lnt的默认内容
C:/lint/std.lnt默认内容可能为空。
我们可以通过运行C:/lint/config.exe来自动生成内容。
3.2.2. 修改std.lnt
运行C:/lint/CONFIG.EXE,
在"Select Your Compiler"(问你的编译器是什么)里选"Microsoft Visual C++ 2008(co-msc90.int)"
在“Architecture"(问你的系统是什么架构)里选“32-bit Flat Model (-ms, -si4 -sp4)”,因为我是为32位的系统测试,你可以按你的产品的架构来改。
在“Libraries"(问你需要用到哪些库)里,我这知道怎么选,最后搞了个“Standard Template Library“
在“Author Recommendations“(问你需要用哪些高手前辈的建议来规范你的代码风格)里选了个"MISRA C 2004"(汽车工业软件可靠性联合会的标准)。
在“Header Files”(问你的系统头文件在哪个路径下)页里选“Create -i options“,在里面输入inclue的路径 C:/Program Files/Microsoft Visual Studio 9.0/VC/include
最后问你是否需要使用你的最新配置为默认设置时,你可以答应,这就覆盖了std.lnt的内容了:
// Microsoft Visual C++ 2008, -si4 -sp4, lib-stl.lnt lib-w32.lnt // Standard lint options au-misra2.lnt co-msc90.lnt lib-stl.lnt lib-w32.lnt options.lnt -si4 -sp4 -i"C:/Program Files/Microsoft Visual Studio 9.0/VC/include" |
注:如果生成的std.lnt内容与上面不一样,可以手工修改成上面那样。
也可以不答应,然后会自动命名为另一个文件:std_A.lnt。你可以在运行lint命令时指定用它就行了。
3.3. 使用std.lnt
再次在命令行下输入:D:/> C:/lint/lint-nt -i"C:/lint" -u std.lnt e:/main.cpp
或者是C:/lint/lint-nt -i"C:/lint" -u std_A.lnt e:/main.cpp
-i"C:/lint" 指明在哪个路径下找配置文件*.lnt
-u std.lnt 指明使用std.lnt这个选项文件.
至此,我们已经学会了PCLINT的简单用法及两个选项:-i,-u
-i 指明包含路径
-u 指明使用哪些.lnt文件
4. 其它开发工具下的配置
前面我们掌握了命令行方式下PCLINT的使用方法,下面介绍在VC下面的配置及使用。
4.1. VC下的配置(我用的是Visual C++ 2008 Express Edition)
点Tools/External Tools...,
新建一自定义工具项,名称为:PClint
Command里定位到你的PLlint:C:\lint\lint-nt.exe
Arguments为:-i"C:/lint" -u std.lnt env-vc9.lnt "$(FileName)$(FileExt)"
Q:怎么知道要输入这样的参数了?
A:从帮助中得知的,见文件env-vc9.lnt
Q: env-vc9.lnt有什么作用?
A:指定输出错误报告的格式,这个选项可以去掉,比如修改为:
Arguments为:-i"C:/lint" -u std.lnt "$(FileName)$(FileExt)"
记得把下面的"Use Output window"钓上,否则你看不到输出了。
4.2. 示例
4.2.1. testForPclint1
新建一个最简单的Win32 Console Application,工程名testForPclint1,其中的main.cpp为:
void main()
{
}
点击Tools菜单下面的PCLINT菜单项:
PC-lint for C/C++ (NT) Ver. 9.00f, Copyright Gimpel Software 1985-2004 --- Module: main.cpp } main.cpp(3): error 783: (Info -- Line does not end with new-line) --- Global Wrap-up error 900: (Note -- Successful completion, 1 messages produced) Press any key to continue |
第三行有个错误:error 783: (Info -- Line does not end with new-line)
意思是说没有以新行结束。
注:如果Arguments为:-i"C:/PCLint" -u std.lnt "$(FileName)$(FileExt)"
则结果为:
PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: main.cpp _ } main.cpp(3) : Info 783: Line does not end with new-line Press any key to continue |
修改main.cpp为:
void main()
{
}<---即在这里加一个回车
再次LINT,结果没有任何告警:
PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: main.cpp --- Global Wrap-up error 900: (Note -- Successful completion, 0 messages produced) Press any key to continue |
4.2.2. testForPclint2
新建一个最简单的Win32 Console Application,工程名testForPclint2,其中的main.cpp为:
#include "stdio.h"
int main(int argc, char* argv[])
{
printf("hello/n");
}
点击Tools菜单下面的PCLINT菜单项:
PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: main.cpp _ } main.cpp(6) : Warning 533: function 'main(int, char **)' should return a value (see line 3) main.cpp(3) : Info 830: Location cited in prior message _ } main.cpp(6) : Info 715: Symbol 'argv' (line 3) not referenced main.cpp(3) : Info 830: Location cited in prior message _ } main.cpp(6) : Info 818: Pointer parameter 'argv' (line 3) could be declared as pointing to const main.cpp(3) : Info 830: Location cited in prior message _ } main.cpp(6) : Info 715: Symbol 'argc' (line 3) not referenced main.cpp(3) : Info 830: Location cited in prior message Press any key to continue |
有4个告警,修改main.cpp为:
#include "stdio.h" int main(int argc, char* argv[]) { (void)argc; // pc lint (void)argv; // pc lint printf("hello/n"); return 0; } |
再次LINT,无任何告警了。
PC-lint for C/C++ (NT) Ver. 8.00q, Copyright Gimpel Software 1985-2004 --- Module: main.cpp Press any key to continue |
5. 使用批处理方法
为什么要使用批处理?还不是为了使用更简单。
我们在C:/lint建一个批处理文件lint.bat,内容为:
@echo off C:/lint/lint-nt -i"C:/lint" -u std.lnt e:/main.cpp |
为了支持输入参数,修改为:
@echo off C:/lint/lint-nt -i"C:/lint" -u std.lnt %1 |
这时候我们不能简单输入D:/>lint.bat,而必须加上输入参数:
D:/>lint.bat e:/main.cpp