C/C++言語の静的解析ツール Splintの紹介です。
C/C++言語の静的解析ツール、使っていますか?仕事で使う場合は有償のもの(QACやpgreliefなど)を使うことがおおいと思います。しかし休みの日に家でコードを書いたりするときにも個人で静的解析ツールを使いたい場合もあると思います。そこで今回は、フリーの静的解析ツール Splintについて説明します。 静的解析ツールを使うことによってコードのバグを減らして品質を上げることができます。また、休みの日に孤独にコードを書いているときでも、 レビューの代わりとして使って自身のコーディング能力をアップさせることもできます。
Splint のインストール
Splintでは「インストール用のバイナリはあまり更新されないから、ソースコードからビルドすることをオススメするよ!」というようなことが書いてあります。 が、自分でビルドするのは手間なので、今回はインストール用のバイナリを素直に使う方法を説明します。
Mac OS X の場合
Homebrew を使えば簡単です。
| |
Linux の場合
Linuxでもパッケージマネージャが対応していれば簡単です。Ubuntuの場合は下記でOKです。
| |
Windows にインストールする場合
Windows向けのインストーラも提供されています。インストール自体は簡単です。他のOSと違って、インストール後に3つの環境変数の設定が必要なのでそれを忘れないでください。
まず、splint_win32に .msi と .zipが置いてありますので、どちらかをダウンロードして、インストールします。 .msiでGUIなインストーラを使用してもいいですし、.zipを解凍して任意のとこに置いてもいいですね。
次に下記の3つの環境変数を設定します。設定の方法は特に特別な手順は必要ありません。
LARCH_PATHLCLIMPORTDIRinclude
普通に、マイコンピューターのアイコンを右クリックして「詳細設定」タブをクリックして「環境変数」から設定すればいいです。 もちろん、コマンドプロンプトから設定してもいいです。
環境変数 LARCH_PATH の設定
LARCH_PATHには、Splintをインストールしたフォルダの直下にあるlibというフォルダのパスを設定してください。
コマンドプロンプトで行うなら下記のようにすればOKです。
ここではSplintをC:\Programs\ の下にインストールしたという前提です。
| |
環境変数 LCLIMPORTDIR の設定
LCLIMPORTDIRには、Splintをインストールしたフォルダの直下にあるimportsというフォルダのパスを設定してください。
コマンドプロンプトで行うなら下記のようにすればOKです。
| |
環境変数 include の設定
最後にincludeの設定です。これにはstdlib.hなどの標準ヘッダファイルのあるフォルダのパスを指定してください。
この変数が設定されていないと、下記のように標準ライブラリのヘッダファイルが見つからないというエラーが出ますので注意してください。
| |
使い方
使い方は簡単です。下記のような感じで .c ファイルを渡すだけです。
| |
ちなみに実際の実行結果は下記のようになります。
| |
引数のオプションについて、ひとまず使うために必要なことを下記に説明します。
ヘッダファイルの探索パスの設定
splintがヘッダファイルを探し出せるように、パスを教えてあげる必要があります。
stdlib.hなどの標準ライブラリは、前述した環境変数include で指定されたところを探しに行きます。
自分で作ったヘッダファイルは、別途教えてあげる必要があります。gccなどの通常のコンパイラと同じく-Iを使います。
例えばカレントディレクトリと../my_includeというディレクトリにヘッダファイルがある場合は、-I./ -I../my_includeとすればOKです。通常のコンパイラと一緒ですね。
ですのでコンパイルしているときのオプションをそのまま渡せば基本的にOKです。
ただし1点だけ注意が必要です。コンパイラの場合は-Iとパスの間にスペースがあっても構いません。例えば-I ./ -I ../my_includeでもOKです。
ですが splint はダメです。必ず -I の直後にはスペースをつけずに、すぐにパスを書くようにしてください。
標準ライブラリなどの設定
どのライブラリを使うかの設定が必要です。デフォルトではC言語のライブラリ(ANSI)が設定されています。
もし、C言語の標準でないPOSIX関数を使っている場合は posix-libを指定してください。よくわからなければPOSIXにしておけば大丈夫でしょう。
ここで注意点があります。ライブラリを指定するときはハイフン- でなくプラス+を使用してください。
つまりsplint -posix-libでなくsplint +posix-libとしてください。
基本的にSplintではハイフン-は無効化、プラス+は有効化を示します。
フラグの設定
どのような指摘を有効にするか、または無効にするかを細かく指定できます。ただし、通常のLinuxコマンドとは作法が異なるので注意してください。
普通のコマンドは、-hogeのようにハイフン-でオプションを指定しますが、Splintはプラス+とハイフン-を使い分けなければいけません。
プラス+は有効か、ハイフン-は無効化の意味となります。例えばhogeという指摘を有効にしたい場合は-hogeでなく+hogeとします。
-hogeは無効にするという意味になってしまいます。
例として、バッファーオーバーフローにつながる可能性のある関数を使用している場合に指摘するbufferoverflowhigh を有効にする場合、
splint +bufferoverflowhighのように指定します。すると下記のような指摘が出力されます。
ちなみにこれは sprintf を使っているから怒られていますね。snprintfを使うべきでしょう。
| |
どのようなフラグがあるかは、Appendix Bを参照してください。
Makefile の書き方の例
Splintの利用例として、Makefile をどのように書けばいいかを説明します。
インクルードパスの設定
前述した通り、Splintを使うときにはヘッダファイルのあるパスを指定しなければいけません。
すでにMakefileでビルド環境が構築している場合は簡単に設定できます。
例えば下記のような、.cファイルから.oファイルをコンパイルするためのパタンルールがあったとします。
CFLAGS変数にヘッダのパス設定-Iも含まれているとします。
| |
このCFLAGSから-Iオプションだけ取り出すには $(filter -I%,\$(CFLAGS))とすればOKです。下記のようにすればOKです。
| |
ここで注意点が1つあります。 コンパイラは-I ../my_includeのように -Iとパスの間にスペースがあってもOKですが、SplintではNGです。
-Iのあとにスペースを入れないでください。-I../my_includeのようにしてください。
最後に、システムのヘッダファイルを解析しないようにします。
通常システムに問題はないはずですし、指摘があってもおいそれと変更できませんしね。
オプションは +skip-sys-headers をつければOKです。
| |
ライブラリの設定
プログラムがつかうライブラリを指定してあげる必要があります。
ANSIかPOSIXかUnixのどれかを選択します。ANSIなら +ansi-lib POSIXなら +posix-lib Unixなら +unix-lib のオプションをわたします。
μITRONのようなLinuxコマンドを使わない環境ならANSI、LinuxなどはPOSIXとすればよいかと思います。ここではPOSIXにしてみました。
| |
終了ステータスの処理
Splintは一つでも指摘があるとエラーステータスを返します。
そのため、そこで make が中断されてしまいます。
make にて途中でエラーが出ても全コマンドを実行する方法にその対処法を書いていますのでご参照ください。
最終的には下記のようにすればOKです。
| |
gnu-make-framework-zen にMakefile 全体を置いていますので、興味があればみてみてくださいませ。
まとめ
フリーの静的解析ツール Splintのインストールと設定の仕方から Makefile の設定方法までを説明しました。
かなり細かいことまで指摘してくれるツールであり、またフリーですので、いちど試してみてはいかがでしょうか?
おもいもよらぬ指摘がでたりするかもしれませんよ!