一、Clang Static Analyzer 簡介
Clang Static Analyzer 是一個工業級的靜態源碼檢測工具,可以用來發現 C、C++ 和 Objective-C 程序中的 Bug。它既可以作為一個獨立工具(scan-build)使用,也可以集成在 Xcode 中使用。
Clang Static Analyzer 建立在 Clang 和 LLVM 之上。嚴格地講,它是 Clang 的一部分,因此它是完全開源的。Clang Static Analyzer 使用的靜態分析引擎被實現為一個 C++ 庫,可以在不同的客戶端中重用,因此擁有很高的可擴展性。
二、scan-build 的使用
scan-build 就是 Clang Static Analyzer 的命令行工具。在 Clang 的二進制包中就可以直接找到它的身影,一般它與 Clang/Clang++ 同處於一個目錄。
我們從一個示例開始:
1
2
3
4
5
6
7
8
9
|
#include<stdio.h>
#include<stdlib.h>
int main(int argc, const char* argv[]) {
void* ptr = malloc(sizeof(char));
free(ptr);
memset(ptr, 0, sizeof(char) * 2);
return 0;
}
|
scan-build 是在編譯過程中檢測代碼的,因此必須和編譯器一起協同工作,可以指定使用 gcc 或者 clang。注意,scan-build 會使用 clang/clang++ 做 analyze,即便指定編譯器為 gcc/g++。
1
|
scan-build -o memleak gcc memleak.c
|
上述命令即對 memleak.c 進行檢測,其中 -o 參數用於指定檢測結果存放路徑,檢測結果會以 html 文件的形式保存:
可看到上述代碼中的內存泄露問題被檢測出來。以上是對於單個源碼文件的檢測,更好的方式是將 scan-build 直接與構建系統串接起來一起協同工作:
1
|
$ scan-build --use-cc gcc --use-c++ g++ make
|
三、使用 scan-build 處理交叉編譯
交叉編譯的場景下,除了指定 toolchain 之外,還要指定 analyzer-target,另外還需要指定 C/C++ 的 include 路徑:
1
2
3
4
5
6
7
|
$ C_INCLUDE_PATH=path_1:path_2:...:path_n \
CPLUS_INCLUDE_PATH=path_1:path_2:...:path_n \
scan-build \
--use-cc=arm-linux-gnueabihf-gcc \
--use-c++=arm-linux-gnueabihf-g++ \
--analyzer-target=arm-linux-gnueabihf \
make [options]
|
其中 C_INCLUDE_PATH 和 CPLUS_INCLUDE_PATH 這兩個變量都支持指定多個路徑,中間使用冒號分隔。
對於大型程序,scan-build 會顯著拖慢編譯速度。另外,這類靜態代碼檢測工具也有它的局限性,像內存訪問越界類似的問題就不太可能檢測得到,這時就要靠 Valgrind 和 Address Sanitizer 這些運行時的內存調試工具了。
參考: