- 論壇徽章:
- 0
|
PC-Lint是一款C/C++軟件代碼靜態(tài)分析工具,不僅可以檢查一般的語(yǔ)法錯(cuò)誤,還可以檢查潛在的錯(cuò)誤,比如數(shù)組訪問(wèn)越界、內(nèi)存泄漏、使用未初始化變量、使用空指針等。在單元測(cè)試前使用PC-Lint來(lái)檢查代碼,可以提前發(fā)現(xiàn)程序中的潛在的錯(cuò)誤,提高代碼
的質(zhì)量。
本文主要從兩個(gè)方面介紹PC-lint,第一部分是在與不同的工具安裝集成,第二部分是PC-lint的使用方法。
1. 安裝PC-lint及如何集成到VC6.0和Source Insight
1.1 安裝PC-lint
(1)下載PC-lint(PC-Lint 8.00w)。
(2)將下載的壓縮包解壓至到D盤,并對(duì)文件夾重命名為PC-Lint,這樣路徑為D:\PC-Lint。
備注:這也叫安? 呵呵,似乎算免安裝更合適吧。
1.2 將PC-lint集成到VC6.0
1.2.1 對(duì)單個(gè)C/C++進(jìn)行靜態(tài)代碼分析
(1)將D:\PC-Lint\lnt 下的3個(gè)文件lib-w32.lnt,env-vc6.lnt,co-msc60.lnt復(fù)制到D:\PC-Lint\下。
(2)打開(kāi)co-msc60.lnt,將該文件倒數(shù)第二行"lib-ole.lnt"的內(nèi)容改為"D:\PC-Lint\lnt\lib-ole.lnt",也就是在前面加上絕對(duì)路徑,以免在后面的步驟中無(wú)法找到該文件。
(3)在D:\PC-Lint\下創(chuàng)建std.lnt和options.lnt兩個(gè)文件,其中std.lnt的內(nèi)容如下:
注:-i后面的路徑名為VC 6.0的安裝路徑和及其頭文件路徑;options.lnt可以暫時(shí)為空。
(4)在VC6.0的菜單欄中,Tools--->Customize...-->tools 新建一個(gè)名為pclint的項(xiàng),在下面填入
"Command"項(xiàng)填入: D:\PC-Lint\lint-nt.exe
"Argument"項(xiàng)填入: -u D:\PC-Lint\std.lnt D:\PC-Lint\env-vc6.lnt "$(FilePath)"
然后在Use Output Window 打上勾即可。
(5)在VC6.0的菜單欄Tools下多了一個(gè)pclint選項(xiàng),打開(kāi)一個(gè)VC項(xiàng)目后,就可以使用該選項(xiàng)對(duì)單個(gè)C/C++文件進(jìn)行靜態(tài)代碼分析了。
1.2.2 對(duì)一個(gè)VC6.0項(xiàng)目進(jìn)行靜態(tài)代碼分析
下面的步驟是在1.2.1的前三步的基礎(chǔ)上進(jìn)行的。
(1)先到http://www.weihenstephan.de/~syring/win32/UnxUtils.zip下載UnxUtils.zip。需要利用unix中的find等命令來(lái)查找當(dāng)前目錄下的C和C++文件,然后再將它們送給lint程序處理。
(2)解壓UnxUtils.zip到D盤,這樣路徑為D:\UnxUtils。
(3)在在VC6.0的菜單欄Tools下多了一個(gè)pclint_prj選項(xiàng),打開(kāi)一個(gè)VC項(xiàng)目后,就可以使用該選項(xiàng)對(duì)單個(gè)C/C++文件進(jìn)行靜態(tài)代碼分析了。
"Command"項(xiàng)填入: D:\UnxUtils\usr\local\wbin\find.exe
"Argument"項(xiàng)填入: $(FileDir) -name *.c -o -name *.cpp | D:\UnxUtils\usr\local\wbin\xargs D:\PC-Lint\lint-nt -i"D:\UnxUtils\usr\local" -u D:\PC-Lint\std.lnt D:\PC-Lint\env-vc6.lnt
然后在Use Output Window 打上勾即可。
(4)在VC6.0的菜單欄Tools下多了一個(gè)pclint_prj選項(xiàng),打開(kāi)一個(gè)VC項(xiàng)目后,就可以使用該選項(xiàng)對(duì)VC項(xiàng)目進(jìn)行靜態(tài)代碼分析了。
注意:"Argument"項(xiàng)填的內(nèi)容一定要注意參數(shù)中的路徑,如果你不使用上述路徑,可以用新路徑將參數(shù)中的路徑替換,以免重新寫參數(shù)而導(dǎo)致出錯(cuò)。
1.3 將PC-lint集成到Source Insight 3.5中
1.3.1 對(duì)單個(gè)C/C++進(jìn)行靜態(tài)代碼分析
(1)打開(kāi)SourceInsight, 選擇Options-->Custom Commands-->Add, 輸入pclint
(2)在Run中填寫: D:\PC-Lint\lint-nt -u D:\PC-Lint\std.lnt D:\PC-Lint\env-vc6.lnt %f
(3)Dir不用填寫,將Iconic Window, Capture Output, Parse Links in OutPut,三項(xiàng)勾選上,并將File,then Line的單項(xiàng)選擇也選上。
(4)然后點(diǎn)右側(cè)的Menu...,在彈出的界面中在下拉框Menu中選擇View,然后在下面的Menu Cotents中選擇<end of menu>, 右側(cè)點(diǎn)Insert即可。
(5)可以在Source Insight 3.5菜單View下看到剛才新建的項(xiàng)pclint,打開(kāi)項(xiàng)目的任意一個(gè)待分析的源文件,運(yùn)行pclint即可進(jìn)行靜態(tài)代碼分析了。
1.3.2 對(duì)一個(gè)項(xiàng)目進(jìn)行靜態(tài)代碼分析
下面的步驟是在1.2.2的基礎(chǔ)上進(jìn)行的。
(1)打開(kāi)SourceInsight, 選擇Options-->Custom Commands-->Add, 輸入pclint_prj
(2)在Run中填寫:
D:\UnxUtils\usr\local\wbin\find.exe %d -name *.c -o -name *.cpp | D:\UnxUtils\usr\local\wbin\xargs D:\PC-Lint\lint-nt -i"D:\UnxUtils\usr\local" -u D:\PC-Lint\std.lnt D:\PC-Lint\env-vc6.lnt
(3)Dir不用填寫,將Iconic Window, Capture Output, Parse Links in OutPut,三項(xiàng)勾選上,并將File,then Line的單項(xiàng)選擇也選上。
(4)然后點(diǎn)右側(cè)的Menu...,在彈出的界面中在下拉框Menu中選擇View,然后在下面的Menu Cotents中選擇<end of menu>, 右側(cè)點(diǎn)Insert即可。
(5)可以在Source Insight 3.5菜單View下看到剛才新建的項(xiàng)pclint_prj,打開(kāi)項(xiàng)目,運(yùn)行pclint_prj即可對(duì)項(xiàng)目進(jìn)行靜態(tài)代碼分析了。
2.PC-lint的用法
2.1 pc-lint目錄下幾個(gè)重要的文件及程序
lint-nt.exe:PC-lint的可執(zhí)行程序。
config.exe: PC-lint的配置文件程序。
pc-lint.pdf:PC-lint的PDF格式的在線手冊(cè),本文的大部分內(nèi)容是從中得來(lái)的。
msg.txt: 對(duì)于錯(cuò)誤消息編號(hào)的詳細(xì)解釋。
Lnt\: 這個(gè)目錄下有些東西還是值得認(rèn)識(shí)一下。
co-....lnt: 指定的編譯器的可選編譯文件。
co.lnt: 通用的可選編譯文件。
sl-....c 非ANSI編譯器的標(biāo)準(zhǔn)庫(kù)文件模塊
sl.c: 非ANSI編譯器的通用標(biāo)準(zhǔn)庫(kù)文件模塊
env-....lnt:不同平臺(tái)下的可選文件,包括MS Visual Studio和其他各種編輯工具。
lib-....lnt:可選文件, 特定的"有挑戰(zhàn)性"的庫(kù)文件。
au-....lnt: 可選文件, 作者們推薦的檢測(cè)條件。
2.2 PC-lint的介紹
2.2.1 錯(cuò)誤信息編號(hào)
對(duì)于大部分的錯(cuò)誤消息,PC-lint都提供了一個(gè)關(guān)聯(lián)的錯(cuò)誤編號(hào)。小于1000的錯(cuò)誤編號(hào)是分配給C語(yǔ)言的,1000以上的錯(cuò)誤編號(hào)則是分配給C++語(yǔ)言的。1000呢?呵呵,被保留了。先看一個(gè)表格。
C C++ 告警級(jí)別
語(yǔ)法錯(cuò)誤(Syntax Errors) 1 - 199 1001 - 1199 1
內(nèi)部錯(cuò)誤(Internal Errors) 200 - 299 0
致命錯(cuò)誤(Fatal Errors) 300 - 399 0
告警(Warnings) 400 - 699 1400 - 1699 2
提示(Informational) 700 - 899 1700 - 1899 3
可選信息(Elective Notes) 900 - 999 1900 - 1999 4
對(duì)于C語(yǔ)言,1~199是與語(yǔ)法錯(cuò)誤;200~299是PC-lint內(nèi)部錯(cuò)誤,應(yīng)該決不會(huì)發(fā)生的;300~399是致命錯(cuò)誤,通常是由于超越了某些限制;400~699是警告消息,提示被檢查的程序中可能存在錯(cuò)誤;700~899是提示信息,這些提示信息可能有錯(cuò)誤,也可能是合法的程序,取決于個(gè)人的編程風(fēng)格;900~999則是一些稱為可選信息,一般不會(huì)自動(dòng)輸出。
PC-lint提供了高級(jí)級(jí)別設(shè)置選項(xiàng)-wLevel,缺省的級(jí)別為3級(jí)。-w0, -w1 , -w2, -w3, -w4 分別可以生成上述表格中對(duì)應(yīng)告警級(jí)別和級(jí)別更低的告警,其中級(jí)別越低告警越重要。同樣,也提供了處理庫(kù)函數(shù)的頭文件告警級(jí)別的選項(xiàng)-wlib(Level),缺省的級(jí)別也是3級(jí),級(jí)別對(duì)應(yīng)的含義與前者一樣。
2.2.2 選項(xiàng)的規(guī)則
通過(guò)使用加號(hào)"+"和減號(hào)"-",以注釋的形式插入代碼中,來(lái)恢復(fù)和屏蔽指定的被檢查的選項(xiàng)。格式如下:
/*lint option1 option2 ... optional commentary */
或者
//lint option1 option2 ... optional commentary
注意:lint必須是小寫,選項(xiàng)的一行不能超過(guò)80個(gè)字符,否則導(dǎo)致致命的錯(cuò)誤,錯(cuò)誤信息的編號(hào)就是323。如果選項(xiàng)確實(shí)有很長(zhǎng),可以通過(guò)換行的方式來(lái)實(shí)現(xiàn)。另外屏蔽和恢復(fù)的選項(xiàng)的代碼可以放在宏定義中,宏被展開(kāi)后,這些選項(xiàng)會(huì)生效。
2.2.3 選項(xiàng)中的空格
因?yàn)榭崭袷怯脕?lái)分隔選項(xiàng)的,除此之外只能出現(xiàn)在圓括號(hào)的旁邊或是空格自身被引用(例如operator new按語(yǔ)法要求中間就有空格)。舉個(gè)例子:
-esym(534,printf,scanf,operator new)
-esym(534, printf, scanf, operator new)
-esym( 534 , printf , scanf , operator new )
對(duì)于第三個(gè),空格出現(xiàn)在圓括號(hào)的旁邊,也出現(xiàn)在自身被引用的地方(operator new)。另外operator和new之間出現(xiàn)兩個(gè)空格也是不合法的,因?yàn)樗`反了語(yǔ)法規(guī)則。另外,也可以使用雙引號(hào)("" 來(lái)保護(hù)空格,例如:
-"dWORD=unsigned short"
2.2.4 選項(xiàng)的分類
PC-lint的選項(xiàng)有300多種,可以分為下面幾類:
(1)禁止錯(cuò)誤信息
選項(xiàng)開(kāi)頭使用"-e"可以禁止指定的錯(cuò)誤消息,使用"+e"恢復(fù)指定的錯(cuò)誤消息。如果禁止消息,只不過(guò)不讓消息輸出,并不影響PC-lint的處理過(guò)程。順便提一下前面提到的"-wLevl",這個(gè)選項(xiàng)是禁用指定級(jí)別及以上的消息的顯示。
1)格式一:
-e# 禁止指定的錯(cuò)誤消息,#代表數(shù)字或是數(shù)字匹配符,錯(cuò)誤消息的編號(hào)為#。
+e# 恢復(fù)指定的錯(cuò)誤消息,錯(cuò)誤消息的編號(hào)為#。
舉個(gè)例子:
/*lint -504*/
...Code.....
/*lint +504*/
第一行關(guān)閉了編號(hào)為504的錯(cuò)誤消息,最后一個(gè)行則重新打開(kāi)了編號(hào)為504的錯(cuò)誤消息。其中數(shù)字也可以包含匹配符號(hào),'?'匹配單個(gè)字符,"*"匹配多個(gè)字符。
比如:
(1)-e7???, 則關(guān)閉了700~799這個(gè)范圍內(nèi)的錯(cuò)誤消息。
(2)-e1*, 則關(guān)閉了所有以1開(kāi)頭的編號(hào)的錯(cuò)誤消息。
同樣匹配符也能使用在-esym, -elib, -elibsym, -efile, -efunc, -emacro, -etemplate, -e(#), --e(#), -e{#} and –e{#}.
2)格式二:
-e(#[,#]...) 為下一個(gè)表達(dá)式禁止指定的錯(cuò)誤消息,在這個(gè)表達(dá)式結(jié)束后被禁止的錯(cuò)誤消息自動(dòng)恢復(fù),#代表數(shù)字或是數(shù)字匹配符,錯(cuò)誤消息的編號(hào)為#。
舉個(gè)例子:
a = /*lint -e(413) */ *(char *)0;
它等價(jià)于下面的語(yǔ)句:
a = /*lint -save -e413 */ *(char *)0
/*lint -restore */;
前一種方法更簡(jiǎn)單且更有效。
3)格式三:
--e( # [,#]... ) 比上面的那個(gè)管的更寬一些,它對(duì)整個(gè)表達(dá)式有效,舉個(gè)例子就明白它與上面的區(qū)別了。
舉個(gè)例子:
a = /*lint --e(413) */ *(int *)0 + *(char *)0;
整個(gè)表示式是指*(int *)0 + *(char *)0,下個(gè)一表達(dá)式指的是*(int *)0。區(qū)別一目了然,例子中將禁止兩個(gè)編號(hào)為413 的錯(cuò)誤消息, 如果使用 -e(413) ,則只禁止第一個(gè)編號(hào)為 413 的錯(cuò)誤消息。
4)格式四:
-e{ # [, #] …} 對(duì)下一個(gè)語(yǔ)句或者聲明有效
舉個(gè)例子:
//lint -e{715} suppress "k not referenced"
void f( int n, unsigned u, int k )
{
//lint -e{732} suppress "loss of sign"
u = n; // 732 not issued
//lint -e{713} suppress "loss of precision"
if(n)
{
n = u; // 713 not issued
}
} // 715 not issued
通過(guò)例子可以看出,這種格式放在函數(shù)之前,則對(duì)整個(gè)函數(shù)產(chǎn)生作用,放在賦值語(yǔ)句前則只對(duì)賦值語(yǔ)句起作用,放在if或while前面,則對(duì)這一段語(yǔ)句起作用。在C++的類定義或命名空間聲明前放這么個(gè)選項(xiàng),則將整個(gè)類或命名空間內(nèi)的代碼中指定的錯(cuò)誤消息給禁止了。
5)格式五:
--e{ # [, #] … } 對(duì)于其所處的 {} 號(hào)區(qū)域內(nèi)的整個(gè)代碼體有效。 {} 號(hào)區(qū)域可能是復(fù)雜的語(yǔ)句、函數(shù)體、C++的類,結(jié)構(gòu)體或聯(lián)合體的定義、C++的命名空間等。如果這個(gè)選項(xiàng)放在一個(gè)模塊前,而模塊前沒(méi)有 {},則對(duì)整個(gè)模塊生效。
6)格式六:
!e# 僅對(duì)其所在行有效。
if( x = f(34) ) //lint !e720
y = y / x;
在這個(gè)例子中,僅對(duì)那一行禁止編號(hào)為720 的錯(cuò)誤消息?匆幌翪語(yǔ)言的代碼的用法:
if( x = f(34) ) /*lint !e720 */
y = y / x;
如果有更多的錯(cuò)誤信息要禁止,而又無(wú)法使用通配符,則可以使用下面的方法:
n = u / -1; //lint !e573 !e721
7)格式七:
-ealetter 參數(shù)不匹配禁止
格式八:
-efile( #, file [, file] ... ) inhibits and
+efile( #, file [, file] ... ) re-enables
9)格式九:
-efunc( #, Symbol [, Symbol] ... ) inhibits and
+efunc( #, Symbol [, Symbol] ... ) re-enables
10)格式十:
-elib( # [, #] ... ) inhibits and
+elib( # [, #] ... ) re-enables
11)格式十一:
-elibsym( # [, # ] ... ) inhibits
+elibsym( # [, # ] ... ) re-enables
12)格式十二:
-emacro( #, symbol, ... )
+emacro( #, symbol, ... )
13)格式十三:
-emacro( (#), symbol, ... )
--emacro( (#), symbol, ... )
-emacro( {#}, symbol, … )
--emacro( {#}, symbol, … )
14)格式十四:
-esym( #, Symbol [, Symbol] ... ) inhibits and
+esym( #, Symbol [, Symbol] ... ) re-enables
禁止和恢復(fù)指定的符號(hào)的錯(cuò)誤消息。舉個(gè)C++的例子(實(shí)際應(yīng)用中不太可能出現(xiàn)):
class X
{
void f(double, int);
};
分析結(jié)果中會(huì)提示某行的member X::f(double, int)沒(méi)有被引用,為了屏蔽這個(gè)消息,你可以使用
-esym( 754, X::f )
符號(hào)的完整簽名為X::f(double, int),然而符號(hào)的名字為X::f,而且可以使用符號(hào)的名字來(lái)禁止錯(cuò)誤消息的出現(xiàn)。另外,-esym 和 -e# 選項(xiàng)是獨(dú)立的,舉個(gè)例子:
-e714 +esym( 714,alpha )
對(duì)于alpha來(lái)說(shuō),它禁止了編號(hào)為714的錯(cuò)誤消息,第二個(gè)選項(xiàng)并不會(huì)恢復(fù)編號(hào)為714的錯(cuò)誤消息,除非前面有個(gè)對(duì)應(yīng)的-esym(714,alpha)。
15)格式十五:
-etd( TypeDiff [, ...] ) inhibits
+etd( TypeDiff [, ...] ) re-enables
16)格式十六:
-etemplate( # [,#] ... )
+etemplate( # [,#] ... )
禁止和恢復(fù)在擴(kuò)展模板(expanding templates)時(shí)的錯(cuò)誤消息。
(2)變量類型大小和對(duì)齊選項(xiàng)
1)變量類型大小選項(xiàng)
這組選項(xiàng)允許設(shè)置各種變量類型的大小和對(duì)齊方式。由于默認(rèn)的設(shè)置于絕大多數(shù)的編譯器都是一致的,所以這些參數(shù)的單獨(dú)設(shè)置通常是沒(méi)有必要的。使用變量類型大小的選項(xiàng)是為了特定的架構(gòu),而不是本地架構(gòu)。舉個(gè)例子,你需要為嵌入式系統(tǒng)設(shè)置int和pointers通常為16位,那么你應(yīng)該指定:
lint -si2 -sp2 ...
下面的列表,#號(hào)代表一個(gè)小的整型值,僅舉幾個(gè):
-sb# 字節(jié)的位數(shù)為#,默認(rèn)的是-sb8,
-sbo# sizeof(bool)就變?yōu)橐粋(gè)參數(shù)了,默認(rèn)值為1,
-sc# sizeof(char) 就變?yōu)?#,默認(rèn)值為1,
-slc# sizeof(long char) 就變?yōu)?#,默認(rèn)值為2,
...
2)對(duì)齊選項(xiàng)
僅有兩個(gè)可選擇的注釋信息來(lái)檢測(cè)不規(guī)律的對(duì)齊,它們的錯(cuò)誤編號(hào)是958和959,詳細(xì)的介紹就省略了吧。
(3)冗長(zhǎng)信息選項(xiàng)
冗長(zhǎng)信息選項(xiàng)采用-v和+v開(kāi)頭來(lái)控制,冗長(zhǎng)信息指的是在檢測(cè)過(guò)程中產(chǎn)生的一些與編譯過(guò)程有關(guān)的信息,或者說(shuō),冗長(zhǎng)信息與編譯過(guò)程中消息的頻率和種類有關(guān)。如果使用-v,則冗長(zhǎng)信息進(jìn)被發(fā)送到標(biāo)準(zhǔn)輸出,而是用+v,冗長(zhǎng)信息進(jìn)則會(huì)被發(fā)送到標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤中。如果要將錯(cuò)誤信息重定向到一個(gè)文件中,并想要在終端查看冗長(zhǎng)信息和被解釋后的錯(cuò)誤消息,+v選項(xiàng)是非常有用的。
(4) 標(biāo)志選項(xiàng)
采用+f,++f,-f,--f開(kāi)頭開(kāi)介紹標(biāo)志位。一個(gè)標(biāo)志位在內(nèi)部采用一個(gè)整型值表達(dá)。通過(guò)認(rèn)為:
ON 假如整型值大于0
OFF 假如整型值小于或等于0
默認(rèn)設(shè)置時(shí)1為ON,0為off,對(duì)于的關(guān)系如下:
+f...:通過(guò)把標(biāo)志為設(shè)置為1而把它設(shè)置為ON
-f...:通過(guò)把標(biāo)志為設(shè)置為0而把它設(shè)置為OFF
++f...:標(biāo)志位增1
--f...:標(biāo)志位減1
后面兩個(gè)選項(xiàng)在只設(shè)置局部標(biāo)志而不影響全局設(shè)置時(shí),非常有用。
(5)消息顯示選項(xiàng)
消息顯示選項(xiàng)用于定義消息輸出的格式。
1)控制錯(cuò)誤消息的高度。
-h選項(xiàng)被用來(lái)控制消息的高度,通常的格式如下:
-h[F][f][a][r][mn][m][m/M/][I]N
s 表示每條消息后的空格。其他的就不介紹了。
2)控制錯(cuò)誤消息的寬度。
格式如下:
-width(W,Indent)
例如:-width(99,4)
3)消息格式化選項(xiàng)
格式如下
-format=...
3)附加信息選項(xiàng)
格式如下:
-append(errno,string)
(6)其他選項(xiàng)
1)-A 要求嚴(yán)格使用ANSI C/C++處理。
其他的不介紹了。
2.2.5 庫(kù)文件檢查
這里的庫(kù)文件時(shí)指那些編譯后的庫(kù)文件,比如標(biāo)準(zhǔn)的I/O庫(kù),又比如第三方的庫(kù)文件,例如windows的庫(kù)文件。關(guān)注庫(kù)文件的重要特色是因?yàn)橐韵聝牲c(diǎn):
(1)庫(kù)文件的源代碼通常不可獲得。
(2)庫(kù)文件在多個(gè)正被你使用pc-lint檢查的程序中使用。
庫(kù)的頭文件描述了庫(kù)的部分或完整的接口。舉個(gè)例子:
hello.c
#include <stdio.h>
main()
{
HelloWorld();
printf( "hello world\n" );
}
如果沒(méi)有"#include <stdio.h>"這一行代碼,使用PC-lint檢查上述代碼,PC-lint會(huì)抱怨printf()既沒(méi)有聲明也沒(méi)有定義,會(huì)給出編號(hào)為718錯(cuò)誤信息。如果"stdio.h"被當(dāng)做一個(gè)庫(kù)文件的頭文件,那么PC-lint不會(huì)要求給出printf()的源代碼。
(1)格式一:
+libclass( identifier[, identifier] ... )
用來(lái)指定名為identifier的頭文件當(dāng)做庫(kù)頭文件。identifier是其中下面之一:
angle: 所有尖括號(hào)包含起來(lái)的頭文件
foreign:所有在搜索列表中目錄下的頭文件
ansi:標(biāo)準(zhǔn)ANSI C/C++ 的頭文件
all:所有頭文件
默認(rèn)情況下,+libclass(angle,foreign) 是有效的,這也是為什么hello.c的代碼沒(méi)有要求給出printf()源代碼的原因。
(2)格式二:
+libdir( directory [, directory] ... )
-libdir( directory [, directory] ... )
指定目錄的。
(3)格式三:
+libh( file [, file] ... )
-libh( file [, file] ... )
增加或移出那些已經(jīng)被 +libclass 和 +/-libdir 已確定的頭文件,以達(dá)到要求或不要求給出源代碼。舉個(gè)例子:
+libclass( ansi, angle )
+libh( windows.h, graphics.h )
+libh( os.h ) -libh( float.h )
要求所有的ansi和angle(除了float.h),還有那三個(gè)windows.h, graphics.h, os.h也會(huì)被當(dāng)做庫(kù)頭文件。
2.2.6 強(qiáng)類型檢查
什么是強(qiáng)類型?C/C++的變量都有類型,不同類型之間的賦值可能會(huì)產(chǎn)生告警,可以說(shuō)C/C++變量的類型是強(qiáng)類型。有強(qiáng)類型,自然有弱類型。比如一些腳本語(yǔ)言,它們的變量就不存在具體的類型,可以相互之間賦值,它們就是弱類型語(yǔ)言。為什么在使用PC-lint對(duì)C/C++進(jìn)行檢查時(shí),要進(jìn)行強(qiáng)類型檢查呢?因?yàn)橛兄T如使用typedef定義的數(shù)據(jù)類型,可以避開(kāi)編譯器的類型檢查。舉個(gè)例子:
typedef int Count;
typedef int Bool;
Count n;
Bool stop;
...
n = stop ;
對(duì)于這段代碼,編譯器是不會(huì)告警的,但是最后一行代碼是錯(cuò)誤的。所以,強(qiáng)類型檢查選項(xiàng)是必要的。
強(qiáng)類型檢查選項(xiàng)"-strong"和附加選項(xiàng)"-index"可以完全的或部分的對(duì)typedef定義的數(shù)據(jù)類型進(jìn)行強(qiáng)類型檢查,保證相同類型的變量才能相互賦值。
(1)強(qiáng)類型檢查選項(xiàng)strong的格式如下:
-strong( flags[, name] ... )
name是強(qiáng)類型,flags是指定的屬性,flags參數(shù)可以是A、J、X、B、b、l和f。如果name被省略,所有使用typedef定義的數(shù)據(jù)類型的flags的屬性不能被其他的-strong選項(xiàng)所識(shí)別。
flags參數(shù) 弱化字符
A i 忽略初始化
r 忽略Return語(yǔ)句
p 忽略參數(shù)傳遞
a 忽略賦值操作
c 忽略將常量賦值(包括整數(shù)常量、常量字符串等)給強(qiáng)類型的情況
z 忽略Zero賦值
X 當(dāng)把強(qiáng)類型的變量賦值給其他變量的時(shí)候進(jìn)行類型檢查。弱化參數(shù)i, r, p, a, c, z同樣適用于X并起相同的作用。
J 當(dāng)強(qiáng)類型與其它類型進(jìn)行運(yùn)算時(shí)(邏輯運(yùn)算、關(guān)系運(yùn)算、數(shù)學(xué)運(yùn)算等)進(jìn)行檢查
e 忽略==、!=和?:操作符
r 忽略>、>=、<和<=
o 忽略+、-、*、/、%、|、&和^
c 忽略該強(qiáng)類型與常量進(jìn)行以上操作時(shí)的檢查
z 忽略該強(qiáng)類型與Zero進(jìn)行以上操作時(shí)的檢查
B 類型是Boolean,一般情況下只能使用一個(gè)name(指格式中的name), 而且它應(yīng)該和其他flags聯(lián)合使用。
B選項(xiàng)有兩個(gè)作用:
1. 出于強(qiáng)類型檢查的目的,每一個(gè)Boolean操作符都采用返回一個(gè)和Type兼容的類型。Boolean操作符就是那些顯示
為true或false,也包括前面提到的四種關(guān)系運(yùn)算符和兩種等于判斷符,取反操作符!,二元操作符&&和||。
2. 在所有需要判斷Bolean值的上下文中,比如if語(yǔ)句和while語(yǔ)句,都應(yīng)該檢查這個(gè)強(qiáng)類型,否則產(chǎn)生告警。
b 僅僅假定每一個(gè)Bolean類操作符都將返回一個(gè)與Type類型兼容的返回值。與B選項(xiàng)相比,b選項(xiàng)的限制比較寬松。
l 庫(kù)標(biāo)志,當(dāng)強(qiáng)類型的對(duì)象從庫(kù)函數(shù)中獲得值,或者將強(qiáng)類型對(duì)象的值作為參數(shù)傳遞給庫(kù)函數(shù)等情況下,不產(chǎn)生告警。
f 與B或b連用,表示不應(yīng)該將1位長(zhǎng)度的位域當(dāng)做Boolean類型,否則表示1位長(zhǎng)度的位域被缺省假定為Boolean類型。
這些選項(xiàng)順序?qū)δ軟](méi)有影響,但是A和J選項(xiàng)的弱化字符必須緊跟在它們之后。B選項(xiàng)和b選項(xiàng)不能同時(shí)使用,f選項(xiàng)必須搭配B選項(xiàng)或b選項(xiàng)使用,如果不指定這些選項(xiàng),-strong的作用就是僅僅聲明type為強(qiáng)類型而不作任何檢查。下面用一段代碼演示-strong選項(xiàng)的用法:
//lint -strong(Ab,Bool) <選項(xiàng)是以注釋的形式插入代碼中>
typedef int Bool;
Bool gt(int a, b)
{
if(a) return a > b; // OK
else return 0; // Warning
}
代碼中,Bool被聲明成強(qiáng)類型,如果沒(méi)有指定b選項(xiàng),第一個(gè)return語(yǔ)句中的比較操作就會(huì)被認(rèn)為與函數(shù)類型不匹配。第二個(gè)return語(yǔ)句導(dǎo)致告警是因?yàn)?不是Bool類型,如果添加c選項(xiàng),例如-strong(Acb,Bool),這個(gè)告警就會(huì)被禁止。
(2) 另一個(gè)強(qiáng)類型檢查選項(xiàng)是index,格式如下:
-index( flags, ixtype, sitype [, sitype] ... )
這個(gè)選項(xiàng)是對(duì)strong選項(xiàng)的補(bǔ)充,它可以和-strong選項(xiàng)一起使用。這個(gè)選項(xiàng)指定ixtype是一個(gè)排他的索引類型,它可以和強(qiáng)索引類型sitype的數(shù)組(或指針)一起使用,ixtype和sitype被假定為后來(lái)使用typedef聲明來(lái)定義的的類型名稱。flags可以是c或d,c允許將ixtype和常量作為索引使用,而d允許在不使用ixtype的情況下指定數(shù)組的維數(shù)(Dimensions)。
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/scucj/archive/2009/08/06/4409735.aspx |
|