靜態(tài)分析工具Clang Static Analyzer (3) Cppcheck
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
前文介紹CodeChecker時,使用到了Cppcheck,我們來看看這個工具是什么,如何使用。
1、Cppcheck介紹
Cppcheck 是 C/C++ 代碼的靜態(tài)分析工具。它提供獨特的代碼分析技術(shù)來檢測缺陷,不檢查代碼中的語法錯誤,只檢查編譯器檢查不出來的缺陷,并專注于檢測未定義行為錯誤和危險的編碼結(jié)構(gòu)。其目標(biāo)是減少誤報、零誤報,檢查代碼中真正的錯誤。Cppcheck旨在能夠分析C / C++代碼,即使它具有非標(biāo)準(zhǔn)語法(在嵌入式項目中很常見)。
Cppcheck既有開源版本,也有具有擴(kuò)展的功能和支持的Cppcheck Premium版本,??梢栽L問 www.cppchecksolutions.com 以獲取商業(yè)版本的更多信息和購買選項。
(1)Cppcheck功能特性
- 獨特的代碼分析,可檢測代碼中的各種錯誤。
- 命令行界面和圖形用戶界面都可用。
- Cppcheck非常注重檢測未定義的行為。
(2)Cppcheck特有的分析技術(shù)
使用多個靜態(tài)分析工具可能是一個好主意,每個工具都有獨特的功能特性。這在研究中已經(jīng)證實。那么Cppcheck的獨特之處在哪里?
Cppcheck使用不健全的流程敏感分析,其他幾種分析器使用基于抽象解釋的路徑敏感分析,這也很好,但既有優(yōu)點也有缺點。從理論上講,根據(jù)定義,路徑敏感分析比流量敏感分析更好。但實際上,這意味著Cppcheck將檢測其他工具無法檢測到的錯誤。在Cppcheck中,數(shù)據(jù)流分析不僅是“前向”的,而且是“雙向的”。大多數(shù)分析器會診斷這一點,可以確定數(shù)組索引為 1000 時會出現(xiàn)溢出。
Cppcheck還將診斷此問題,當(dāng)x等于1000時,賦值時也會出現(xiàn)數(shù)組越界。
(3)未定義行為Undefined behaviour
- Dead pointers 死指針
- Division by zero 除以零
- Integer overflows整數(shù)溢出
- Invalid bit shift operands無效的位移操作數(shù)
- Invalid conversions無效轉(zhuǎn)化
- Invalid usage of STLSTL 的用法無效
- Memory management內(nèi)存管理
- Null pointer dereferences空指針解引用
- Out of bounds checking越界檢查
- Uninitialized variables未初始化的變量
- Writing const data寫入常量數(shù)據(jù)
2、Cppcheck安裝
Cppcheck也可以從各種包管理器安裝;但是,您可能會得到一個過時的版本。為了獲取更新版本,可以訪問https://github.com/danmar/cppcheck進(jìn)行源碼安裝。
- Debian:
- Fedora:
- macOS:
3、使用入門
第一個測試程序,這里有一段簡單的代碼,我們命名為file1.c。
執(zhí)行cppcheck file1.c,輸出如下:
我們再試試上面說的例子,保存到file2.c。
執(zhí)行cppcheck --enable=all file2.c,輸出如下??梢钥吹贸鲇?個warning和3個style問題。
(1)檢查文件夾
Cppcheck支持檢查文件夾中的所有文件。通常一個項目會有許多源文件,如果需要同時檢查,Cppcheck 可以檢查文件夾中的所有文件.如果 path 是一個文件夾,cppcheck 將遞歸檢查這個文件夾中的所有源文件。
示例輸出如下:
(2)手動檢查文件或使用項目文件
使用 Cppcheck 可以手動檢查文件,通過指定文件/文件夾來檢查和設(shè)置,或者可以使用一個工程文件(cmake/visual studio)。
使用項目文件更快,因為它只需要非常少的配置。
手動檢查文件可以更好的控制分析。
不一定哪種方法會有最好的結(jié)果,建議嘗試一下,可能會得到不同的結(jié)果,發(fā)現(xiàn)大多數(shù) bug 需要使用這兩種方法。
4、嚴(yán)重級別Severities
輸出信息中的嚴(yán)重級別支持如下幾種:
- error 錯誤
when code is executed there is either undefined behavior or other error, such as
a memory leak or resource leak。發(fā)現(xiàn)未定義行為或其他錯誤,例如內(nèi)存泄露、資源泄露 - warning告警
when code is executed there might be undefined behavior可能有未定義行為 - style樣式風(fēng)格
stylistic issues, such as unused functions, redundant code, constness, operator
precedence, possible mistakes.樣式問題,例如未使用行數(shù),冗余代碼,常量性,操作符優(yōu)先級,可能的錯誤等 - performance性能
run time performance suggestions based on common knowledge, though it is
not certain any measurable speed difference will be achieved by fixing these
messages.這些建議只是基于常識,即使修復(fù)這些消息,也不確定會得到任何可測量的性能提升。 - portability可移植性
portability warnings. Implementation defined behavior. 64-bit portability. Some
undefined behavior that probably works “as you want”, etc.可移植性警告。64 位的可移植性,代碼可能在不同的編譯器中運行結(jié)果不同。 - information信息
configuration problems, which does not relate to the syntactical correctness, but
the used Cppcheck configuration could be improved.配置問題,建議在配置期間僅啟用這些
(1)啟用消息
默認(rèn)情況下,只顯示錯誤消息,可以通過 --enable 命令啟用更多檢查。
- 啟用警告消息:
- 啟用性能消息:
- 啟用信息消息:
由于歷史原因 --enable=style 可以啟用警告、性能、可移植性和樣式信息。當(dāng)使用舊 XML 格式時,這些都由 style 表示:
- 啟用警告和性能消息:
- 啟用 unusedFunction 檢查。這不能通過 --enable=style 啟用,因為不會在庫中正常工作。
- 啟用所有消息:
5、常見錯誤修改
- 隱式構(gòu)造問題。
示例: (style) Class ‘Slice’ has a constructor with 1 argument that is not explicit。
解決方法:在Slice構(gòu)造函數(shù)前加上explicit,使其必須顯示構(gòu)造,當(dāng)然這種有時并非必須顯示構(gòu)造。
- 變量未初始化問題。
示例:(warning) Member variable ‘TableFileCreationInfo::file_size’ is not initialized in the constructor.
解決方法:在構(gòu)造函數(shù)中加入變量初始值。
- 變量/函數(shù)未使用問題。
示例:(style) Unused variable: output。
示例:(style) The function ‘rocksmt_wal_iter_status’ is never used。
解決方法:考慮后期是否還需要,不需要的及時刪除,需要的保留。
- raw loop問題。
示例:(style) Consider using std::fill algorithm instead of a raw loop. [useStlAlgorithm]。
示例:(style) Consider using std::transform algorithm instead of a raw loop. [useStlAlgorithm]。
解決辦法:將循環(huán)便利替換為STL標(biāo)準(zhǔn)庫算法函數(shù)。
- 引用傳遞問題。
示例:(performance) Function parameter ‘f’ should be passed by reference.
解決辦法:在聲明function時,能用引用傳遞的盡量使用引用傳遞,盡量避免值傳遞。
- const參數(shù)問題。
示例:(performance) Function parameter ‘s’ should be passed by const reference. [passedByValue]。
解決辦法:形參s前加上const,在函數(shù)中未被修改的變量,盡量聲明為const。