株式会社クリアコード > ククログ

ククログ


Clangの静的解析を使ってコードの潜在的な問題点を探すには

はじめに

LLVMをベースにしたC/C++、Objective-C/C++のコンパイラフロントエンドとしてClangがあります。 Clangプロジェクトでは、コンパイラだけでなく、静的解析ツールも開発しています。

今回は、その静的解析ツールである、scan-buildについて紹介します。

scan-buildをインストールしよう

以下にUbuntu 14.04 LTS(Trusty)でのインストール手順を示します。Trustyでは、clang-3.3、clang-3.4もしくはclang-3.5をインストールできます。 scan-buildはclangパッケージに含まれているので、今回は新しめのバージョンであるclang-3.5をインストールすることにします。*1

% sudo apt-get install clang-3.5

scan-buildを使ってみよう

scan-buildをインストールできたので、実際に試してみましょう。例として使うのは、ククログで何度か登場しているのでおなじみカラムストア機能つき全文検索エンジンGroongaのコードです。

まずは、ソースコードをcloneして、configureファイルを生成します。

% git clone https://github.com/groonga/groonga.git
% cd groonga
% ./autogen.sh

configureファイルが生成されたら、次はconfigureでclangを使うようにします。

% ./configure CC=clang CXX=clang++

では、scan-buildにかけてみましょう。 configureを実行するとMakefileができるので、あとはscan-buildを単に実行するだけです。

% scan-build make

検出された問題点

scan-buildの実行が完了すると、次のようなサマリが最後に出力されます。

scan-build: 216 bugs found.
scan-build: Run 'scan-view /tmp/scan-build-2014-12-22-164614-28182-1' to examine bug reports.

どんな問題が実際に検出されたのか、確認してみましょう。 scan-buildが最後に出力したコマンドの例を実行します。

% scan-view /tmp/scan-build-2014-12-22-164614-28182-1

すると、自動的にブラウザが起動してレポートを表示します。

Bug Summaryのスクリーンショット

Bug Summaryをみると次のような問題が検出されていることがわかります。

  • NULLポインタの参照(の可能性)
  • 代入しているけど使っていない
  • NULLが期待されていない箇所でNULLが渡された

中には可能性があると指摘されているものの、実際には問題ないというケースもあります。そのあたりは確認が必要です。

Reports(問題の詳細)のスクリーンショット

検出された個別の問題については、Reportsのリンクをたどると該当箇所のコードも表示してくれます。

例えば、無駄な代入を行っている箇所として次のような箇所が検出されました。

検出された問題点に対応するコードのスクリーンショット

みるとわかるのですが、whileループの先頭で変数cに先頭の文字を毎回設定しています。しかし、case文の条件であるGRN_LOADER_BEGINでは、スペースを読みとばしたときには、変数cに先頭の文字を設定してからcontinueで抜けています。 つまり、その場合には

1
c = *str;

が重複して実行されています。これは明らかな無駄ですね。

まとめ

今回は、Clangの静的解析ツールを使ってコードの潜在的な問題点や使われていないコードを検出する方法を紹介しました。 scan-buildをうまく使って、既存のコードにつもった埃をキレイにしてみるといいかも知れませんね。

*1 sudo apt-get install clangで標準インストールされるのはclang-3.4です。

2014-12-22

«前の記事: Sphinx 1.3で使えるgettextとバージョン管理の相性の悪さを改善する仕組み 最新記事 次の記事: Firefox OSのサポートサービス開始のお知らせ»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|