はじめに
clangの静的解析機能をlinux上でも使ってみようという趣旨の記事です。clangとは
clangはmacのxcodeでも使用されているC/C++/Objective-Cのコンパイラです。コンパイラ基盤のLLVMのフロントエンドとして動作しオプションなどはgccと互換性があります。
gccと比較して最適化に長けていて、警告やエラーメッセージが判りやすいなどの特徴があります。
環境
CentOS 6.6 x86_64インストール方法
EPELリポジトリの登録
CentOSには標準でclangのパッケージが用意されていないのでEPEL拡張パッケージのリポジトリを追加します。
# wget http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
# rpm -ivh epel-release-6-8.noarch.rpm
clang-analyzerのインストール
# yum install clang-analyzer
(1/4): clang-3.4.2-4.el6.x86_64.rpm | 20 MB 00:19
(2/4): clang-analyzer-3.4.2-4.el6.noarch.rpm | 77 kB 00:00
(3/4): llvm-3.4.2-4.el6.x86_64.rpm | 1.2 MB 00:01
(4/4): llvm-libs-3.4.2-4.el6.x86_64.rpm | 7.8 MB 00:04
依存するLLVMとclangもインストールされます。
使い方
以下のような些末なコードがあったとして・・・
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int func(const char *str, char **dest)
{
*dest = strdup(str);
if (*dest == NULL) return -1;
char *pos = strstr(*dest, "foo");
if (pos != NULL) memcpy(pos, "bar", 3);
return 0;
}
int main(int argc, char **argv)
{
char* src = argv[1];
char* dest;
int ret = func(src, &dest);
printf("%s => %s\n", src, dest);
// free(dest);
return 0;
}
clangの--analyzeオプションで解析
$ clang --analyze zzz.c
zzz.c:19:5: warning: Value stored to 'ret' is never read
ret = func(src, &dest);
^ ~~~~~~~~~~~~~~~~
zzz.c:22:5: warning: Potential leak of memory pointed to by 'dest'
return 0;
^~~~~~~~
2 warnings generated.
scan-buildコマンドでHTMLレポートを作成
$ scan-build clang zzz.c
scan-build: Using '/usr/bin/clang' for static analysis
zzz.c:19:5: warning: Value stored to 'ret' is never read
ret = func(src, &dest);
^ ~~~~~~~~~~~~~~~~
zzz.c:22:5: warning: Potential leak of memory pointed to by 'dest'
return 0;
^~~~~~~~
2 warnings generated.
scan-build: 2 bugs found.
scan-build: Run 'scan-view /tmp/scan-build-2015-04-26-145938-25383-1' to examine bug reports.
$ scan-view /tmp/scan-build-2015-04-26-145938-25383-1
Starting scan-view at: http://127.0.0.1:8181
Use Ctrl-C to exit.
以下のようなHTMLレポートが作成されます。
現実世界では単一のソースファイルに静的解析出来てもあまりうれしくないです・・・
以下はcmakeのプロジェクトに対して使用する場合です。
cmakeで使用する場合
$ cmake -DCMAKE_C_COMPILER=/usr/libexec/clang-analyzer/scan-build/ccc-analyzer -DCMAKE_CXX_COMPILE=/usr/libexec/clang-analyzer/scan-build/c++-analyzer /path/to/src
$ make
最終的なビルドはgccを使用する場合でも静的解析用途に使ってみてはいかがでしょうか?