介紹如何在 Linux 中使用 Cppcheck 靜態程式碼分析工具檢查,偵測 C/C++ 程式的臭蟲。
Cppcheck 是一個適用於 C/C++ 程式碼的靜態分析工具,可以偵測程式碼中的臭蟲(bugs)以及不合理的異常程式結構,其設計原則為低偽陽性(false positives),亦可用於非標準的語法結構(例如嵌入式專案)。
安裝 Cppcheck
若在 Linux 中可以使用各種套件管理工具來安裝 Cppcheck:
# Ubuntu/Debian Linux 安裝 Cppcheck sudo apt-get install cppcheck # Fedora Linux 安裝 Cppcheck sudo yum install cppcheck # macOS 安裝 Cppcheck brew install cppcheck
若是 Windows 作業系統,則可從 Cppcheck 的官方網站下載 MSI 安裝檔案進行安裝。
使用 Cppcheck 檢測程式碼
假設我們有一個含有臭蟲的 C 語言原始碼檔案 source1.c
內容如下:
/* 含有臭蟲的 C 語言原始碼 */ int main() { char a[10]; a[10] = 0; return 0; }
我們可以利用 cppcheck
指令工具來檢測 C 語言原始碼中的臭蟲或漏洞:
# 檢測 C 語言原始碼
cppcheck source1.c
Checking source1.c ... [source1.c:3]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.
經過 Cppcheck 檢測之後,發現操作 a
陣列時超出邊界,這是 C 語言常見的臭蟲。
完整檢測
Cppcheck 預設只會進行基本的檢測,若要啟用其他附加性的檢測功能,可以使用 --enable
指令要啟用的檢測功能:
# 啟用所有附加檢測 cppcheck --enable=all source1.c # 啟用 performance 與 portability 附加檢測 cppcheck --enable=performance,portability source1.c
Cppcheck 可用的檢測功能類型有:
all
:所有檢測。warning
:警告訊息。style
:程式碼風格訊息,包含performance
、portability
。performance
:效能訊息。portability
:可移植性。information
:資訊訊息。unusedFunction
:檢查未使用函數。missingInclude
:檢查遺失的 include 檔案。
詳細的說明可以參考 cppcheck
的說明:
# 參數說明,可查詢可用之附加檢測名稱 cppcheck --help # 列出所有檢測項目 cppcheck --doc # 列出所有錯誤訊息 cppcheck --errorlist
若要對 source1.c
這個 C 語言原始碼檔案進行完整檢測,則可執行:
# 進行完整檢測 cppcheck --enable=all source1.c
Checking source1.c ... [source1.c:3]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. [source1.c:3]: (style) Variable 'a' is assigned a value that is never used.
遞迴檢測
若在執行 cppcheck
時直接指定原始碼的目錄,就會對整個目錄與子目錄下所有的 C/C++ 程式碼進行檢測:
# 遞迴檢測指定目錄下所有原始碼
cppcheck /path/to/project
排除目錄
若要排除指定的目錄,可以使用 -i
參數指定目錄的路徑或名稱:
# 排除指定 samples 目錄 cppcheck -i /path/to/project/samples /path/to/project # 排除所有 samples 目錄 cppcheck -i samples /path/to/project
輸出至檔案
Cppcheck 會將錯誤訊息輸出至標準錯誤(standard error),若要將錯誤訊息儲存至檔案,可以將標準錯誤導向至檔案:
# 遞迴檢測目前目錄下所有原始碼,輸出至 error.txt cppcheck . 2> error.txt
不確定問題
Cppcheck 的設計原則是低偽陽性(false positives),也就是只顯示很確定的問題,如果不是很確定是否有問題的部分,預設則是不顯示。
如果需要 Cppcheck 連同不確定的部分都輸出,可以加上 --inconclusive
參數:
# 連同不確定問題一起輸出 cppcheck --enable=all --inconclusive source1.c
Include 搜尋路徑
若要指定 C/C++ 語言的 include 檔案搜尋路徑,可以使用 -I
參數指定路徑:
# 指定 include 搜尋路徑 cppcheck -I inc1/ -I inc2/ source.cpp
多執行緒
Cppcheck 支援多執行緒(multi-thread)的平行檢測,可以大幅提升檢測速度。
若要使用多執行緒的平行檢測,可以使用 -j
指定執行續數量:
# 以 4 條執行緒平行檢測 cppcheck -j 4 /path/to/project
XML 格式輸出
若要讓 Cppcheck 以 XML 格式輸出錯誤報表,可以加上 --xml
參數:
# 以 XML 格式輸出 cppcheck --xml source1.c
<?xml version="1.0" encoding="UTF-8"?> <results version="2"> <cppcheck version="1.82"/> <errors> Checking source1.c ... <error id="arrayIndexOutOfBounds" severity="error" msg="Array 'a[10]' accessed at index 10, which is out of bounds." verbose="Array 'a[10]' accessed at index 10, which is out of bounds." cwe="119"> <location file="source1.c" line="3" info="Array index out of bounds"/> </error> </errors> </results>