版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/u011012932/article/details/52778149
簡述
Cppcheck 是一種 C/C++ 代碼缺陷靜態檢查工具。不同於 C/C++ 編譯器及很多其它分析工具,它不檢查代碼中的語法錯誤。Cppcheck 只檢查編譯器檢查不出來的 bug 類型,其目的是檢查代碼中真正的錯誤(即:零誤報)。
| 版權聲明:一去、二三里,未經博主允許不得轉載。
介紹
支持的代碼和平台:
- 可以檢查非標准代碼,包括不同的編譯器擴展、內聯匯編代碼等。
- Cppcheck 應該被處理最新 C++ 標准的任何 C++ 編譯器所編譯。
- Cppcheck 應該在任何有足夠 CPU 和內存的平台上工作。
要知道 Cppcheck 有限制,Cppcheck 很少在報告錯誤方面出錯,但有很多 bug,它不能檢測。
通過仔細測試軟件,你會發現軟件中有更多的 bug,而不是使用 Cppcheck。但 Cppcheck 仍可以檢測到在測試和評估軟件時錯過的一些 bug。
開始使用
第一個測試程序
這里有一段簡單的代碼:
int main() { char a[10]; a[10] = 0; return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
將代碼保存進 file.c 文件中,執行:
cppcheck file.c
- 1
注意:執行此命令前,需要將 cppcheck.exe 所在路徑添加至環境變量 PATH 中。
這時,將會從 cppcheck 中輸出:
Checking file.c …
[file.c:4]: (error) Array ‘a[10]’ accessed at index 10, which is out of bounds.
檢查文件夾中的所有文件
通常一個項目會有許多源文件,如果需要同時檢查,Cppcheck 可以檢查文件夾中的所有文件:
cppcheck path
- 1
如果 path 是一個文件夾,cppcheck 將遞歸檢查這個文件夾中的所有源文件。
Checking path/file1.cpp…
1/2 files checked 50% done
Checking path/file2.cpp…
2/2 files checked 100% done
手動檢查文件或使用項目文件
使用 Cppcheck 可以手動檢查文件,通過指定文件/文件夾來檢查和設置,或者可以使用一個工程文件(cmake/visual studio)。
使用項目文件更快,因為它只需要非常少的配置。
手動檢查文件可以更好的控制分析。
不一定哪種方法會有最好的結果,建議嘗試一下,可能會得到不同的結果,發現大多數 bug 需要使用這兩種方法。
檢查時排除某個文件或文件夾
排除一個文件或文件夾有兩個選項,第一個選項是只提供你想檢查的路徑和文件:
cppcheck src/a src/b
- 1
所有位於 src/a 和 src/b 下的文件都會被檢查。
方式二:使用 -i 選項
這時,將會忽略指定的文件/文件夾,使用下面命令在 src/c 將不會被檢查:
cppcheck -isrc/c src
- 1
嚴重性
可能的嚴重性消息有:
-
錯誤
當發現 bug 時使用 -
警告
關於防御性編程,以防止 bug 的建議 -
風格警告
風格有關問題的代碼清理(未使用的函數、冗余代碼、常量性等等) -
可移植性警告
可移植性警告。64 位的可移植性,代碼可能在不同的編譯器中運行結果不同。 -
性能警告
建議使代碼更快。這些建議只是基於常識,即使修復這些消息,也不確定會得到任何可測量的性能提升。 -
信息消息
配置問題,建議在配置期間僅啟用這些。
啟用消息
默認情況下,只顯示錯誤消息,可以通過 --enable 命令啟用更多檢查。
啟用警告消息:
cppcheck --enable=warning file.c
- 1
啟用性能消息:
cppcheck --enable=performance file.c
- 1
啟用信息消息:
cppcheck --enable=information file.c
- 1
由於歷史原因 --enable=style 可以啟用警告、性能、可移植性和樣式信息。當使用舊 XML 格式時,這些都由 style 表示:
cppcheck --enable=style file.c
- 1
啟用警告和性能消息:
cppcheck --enable=warning,performance file.c
- 1
啟用 unusedFunction 檢查。這不能通過 --enable=style 啟用,因為不會在庫中正常工作。
cppcheck --enable=unusedFunction file.c
- 1
啟用所有消息:
cppcheck --enable=all
- 1
不確定消息
默認情況下,如果確定,Cppcheck 只顯示錯誤消息。如果使用 --inconclusive,當分析不確定時,也會寫錯誤消息。
cppcheck --inconclusive path
- 1
這當然會導致錯誤的警告,即使在沒有 bug 的情況下,也可能會報 bug。如果可以接受錯誤的警告,可以使用此命令。
保存結果到文件中
很多時候,會希望將結果保存在一個文件中,可以使用 shell 的管道重定向錯誤輸出到一個文件:
cppcheck file.c 2> err.txt
- 1
多線程檢查
選項 -j 用於指定需要使用的線程數,例如,使用 4 個線程檢查文件夾中的文件:
cppcheck -j 4 path
- 1
注意:這將禁用 unusedFunction 檢查。
平台
應該使用一個與你的目標匹配的平台配置。
默認情況下,如果代碼在本地編譯和執行,Cppcheck 會使用本地平台配置。
Cppcheck 具有用於 Unix 和 Windows 目標的內置配置,可以輕松地使用這些 --platform 命令行標志。
還可以在 XML 文件中創建自己的自定義平台配置。這里有一個例子:
<?xml version="1"?> <platform> <char_bit>8</char_bit> <default-sign>signed</default-sign> <sizeof> <short>2</short> <int>4</int> <long>4</long> <long-long>8</long-long> <float>4</float> <double>8</double> <long-double>12</long-double> <pointer>4</pointer> <size_t>4</size_t> <wchar_t>2</wchar_t> </sizeof> </platform>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
項目
當使用 CMake 或 Visual Studio 時,可以使用 --project 來分析項目。
它會給你快速和簡單的結果,不需要做太多的配置。但很難說這是否將會給你最好的結果,建議試一試它,並嘗試不使用 --project 分析源代碼,看哪個選項更適合。
CMake
Cppcheck 可以理解編譯數據庫,可以用 CMake 生成這些。
例如:
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- 1
文件 compile_commands.json 在當前文件夾中創建。
現在像這樣運行 Cppcheck:
$ cppcheck --project=compile_commands.json
- 1
Visual Studio
可以對單個項目文件(*.vcxproj)或整個解決方案(*.sln)運行 Cppcheck。
在整個解決方案上運行 cppcheck:
$ cppcheck --project=foobar.sln
- 1
在單個項目文件上運行 cppcheck:
$ cppcheck --project=foobar.vcxproj
- 1
注意:還有一個 Visual Studio 插件,允許在 Visual Studio 中運行 cppcheck。
預處理器設置
如果使用 --project,那么 Cppcheck 將使用項目文件中的預處理器設置。
否則,可能需要配置包含路徑,定義等。
定義
這有一個文件,有兩個配置(定義和沒定義 A):
#ifdef A x = y; #else x = z; #endif
- 1
- 2
- 3
- 4
- 5
默認情況下,Cppcheck 將檢查所有預處理器配置(除了那些具有 #error 的配置),所以上述代碼將被分析在當 A 定義和不定義的情況下。
可以使用 -D 更改。當使用 -D 時,cppcheck 將默認只檢查給定的配置,不會檢查其它,這就是編譯器的工作原理。但是可以使用 --force 或 --max-configs 來覆蓋配置數量。
檢查所有配置:
cppcheck file.c
- 1
只檢查配置 A:
cppcheck -DA file.c
- 1
當定義宏 A 時,檢查所有配置:
cppcheck -DA --force file.c
- 1
另一個有用的標志可能是 -U,它未定義符號。 用法示例:
cppcheck -UX file.c
- 1
這意味着 X 沒有定義,Cppcheck 不會檢查當定義 X 時會發生什么。
XML 輸出
Cppcheck 可以生成 XML 格式的輸出。有一個舊的 XML 格式(version 1)和一個新的 XML 格式(version 2)。如果可以,請使用新版本。
舊版本保持向后兼容性。它不會改變,但有一天可能會被刪除。使用 --xml 支持這種格式。
新版本修復一些舊格式的問題。新格式可能會在 cppcheck 的未來版本中更新,並帶有新的屬性和元素。用於檢查文件並以新的 XML 格式輸出錯誤的示例命令:
cppcheck --xml-version=2 file.cpp
- 1
這是一個 version 2 示例:
<?xml version="1.0" encoding="UTF-8"?> <results version="2"> <cppcheck version="1.66"> <errors> <error id="someError" severity="error" msg="short error text" verbose="long error text" inconclusive="true" cwe="312"> <location file0="file.c" file="file.h" line="1"/> </error> </errors> </results>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
<error> 元素
每個錯誤都在 <error> 元素中,屬性:
-
id
錯誤的 id,這些都是有效的符號名稱。 -
severity
error、warning、style、performance、portability、information 中的任何一個。 -
msg
短格式的錯誤消息 -
verbose
長格式的錯誤消息 -
inconclusive
此屬性僅在消息不確定時使用 -
cwe
消息的 CWE ID,此屬性僅在消息的 CWE ID 已知時使用。
<location> 元素
<location> 元素列出所有錯誤相關位置,首先列出主要位置。
屬性:
-
file
文件名,相對路徑和絕對路徑都是可能的。 -
file0
源文件的名稱(可選) -
line
一個數字 -
msg
此屬性尚不存在,但將來可以為每個位置添加一條短消息。
格式化輸出
如果想重新格式化輸出,使它看起來不同,可以使用模板。
要獲得 Visual Studio 兼容的輸出,可以使用 --template=vs:
cppcheck --template=vs gui/test.cpp
- 1
輸出將如下所示:
Checking gui/test.cpp…
gui/test.cpp(31): error: Memory leak: b
gui/test.cpp(16): error: Mismatching allocation and deallocation: k
要獲得 gcc 兼容的輸出,可以使用 --template=gcc:
cppcheck --template=gcc gui/test.cpp
- 1
輸出將如下所示:
Checking gui/test.cpp…
gui/test.cpp:31: error: Memory leak: b
gui/test.cpp:16: error: Mismatching allocation and deallocation: k
可以編寫自己的模式(例如,逗號分隔格式):
cppcheck --template="{file},{line},{severity},{id},{message}" gui/test.cpp
- 1
輸出將如下所示:
Checking gui/test.cpp…
gui/test.cpp,31,error,memleak,Memory leak: b
gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocation: k
支持以下格式說明符:
-
callstack
調用棧 - 如果可用 -
file
文件名 -
id
消息 id -
line
行號 -
message
詳細的消息文本 -
severity
一個消息的類型/等級
支持轉義序列: \b(退格)、\n(換行)、\r(換頁)、\t(水平制表符)
