Perl Hackers Hub

第27回 Perlにおける静的解析(1)

この記事を読むのに必要な時間:およそ 3 分

本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはmoznionこと川上大喜さんで,テーマは「静的解析」です。

静的解析の背景

静的解析とは何か

静的解析とは,プログラムを実際に実行することなくソフトウェアの解析を実現する手法の一つです。静的コード解析や静的プログラム解析と呼ばれることもあります。

一般に静的解析と言った場合,解析の主体がコンピュータであるか人間であるかは問われませんが(人間が解析する場合は「コードレビュー」などと呼ばれるでしょう),本記事では,特に断りがない限りコンピュータによる解析を指すものとします。

静的解析の利点

静的解析を行うことにより,「未使用変数の検出」「コーディングスタイルの不一致の検出」といった人間が行うにはあまりにも単純で退屈な,しかしコードの品質を向上させるためには必要な作業をコンピュータに任せることができます。

また,そうした単純作業とは逆に,クラス間の依存関係の分析注1)といった,人間がやるには複雑で難しい処理についてもコンピュータに肩代わりさせることができます。

加えて,静的解析によって実行時エラーの検出なども行えます。たとえば,Null参照の例外(いわゆるヌルポ)をユニットテストやインテグレーションテストなどのソフトウェアテストで網羅的に検出するのは困難ですが,静的解析の手法を用いることでこれらの問題の検出の一助となる場合があります。

静的解析を実行する方法

静的解析を実現するアプローチとしては,

  • ソースコードをトークナイザによってトークン列に分解してそれを直接評価・解析する方法
  • 分解したトークン列をパーサによって抽象構文木に変換してから解析する方法
  • 言語処理系の出力する中間ファイルを解析する方法

など多岐にわたります。1つ目のトークン列を直接評価および解析する手法は汎用的に使える技術なので,本稿では主にこの方法について述べます。

注1)
たとえば「どのクラスがどのクラスを参照しているか」といったことです。

静的解析の例

実際の静的解析の例を見てみましょう。静的解析の技術やその周辺ツールがほかの言語と比較して豊富なJavaを例に解説します。

未使用のローカル変数の検出

静的解析の代表的な例として,未使用のローカル変数の検出が挙げられます。

検出結果はコンパイラの警告として出力されますが,こうした機能はIDEIntegrated Development Environment統合開発環境)に組み込まれていることが多いでしょう。図1はJavaのIDEであるEclipseにおける未使用ローカル変数の検出例です。使用されていないString型のfooという文字列が検出され,警告とともにハイライトされていることがわかります。

図1 未使用のローカル変数の検出例

図1 未使用のローカル変数の検出例

Checkstyle――コーディングスタイルのチェック

Checkstyleというソフトウェアを利用することでコーディングスタイルのチェックを行えます。CheckstyleはEcpilseをはじめとしたさまざまなIDEのプラグインとしてサポートされているので,簡単に導入できます。

図2では,if文の開き中括弧の直前にホワイトスペースがないことが警告されています。Checkstyleを用いると,このように人間が行うにはつまらない作業を静的解析処理に任せることができます。Checkstyleではこのほかにも,「変数の命名規則に則っているか」「修飾子の整合性がとれているか」といった多岐にわたるチェックを実行できることに加え,ユーザが独自のコーディングスタイルのルールを設定することもできます。

図2 Checkstyleによるコーディングスタイルの不一致の検出例

図2 Checkstyleによるコーディングスタイルの不一致の検出例

FindBugs――潜在的なバグの検出

静的解析によって潜在的なバグの検出も実現できます。JavaではFindBugsというソフトウェアが有名です。FindBugsも多くのIDEでプラグインが提供されています。

図3ではFindBugsを使って,Null参照の例外が発生してしまうコードを検出しています。Null参照の例外は実行時エラーですが,静的解析によって実際にプログラムを実行することなく検出できています。Find Bugsはこれ以外にも多種多様な潜在バグを,静的解析を用いることにより検出できます。

図3 FindBugsによる潜在バグの検出例

図3 FindBugsによる潜在バグの検出例

これらはほんの一例にすぎませんが,静的解析の便利さを感じていただけたと思います。

Perlにおける静的解析の背景と課題

Perlの静的解析が抱えていた問題

先述したように,静的解析を実現するためにはソースコードをトークンレベルにまで分割する必要があります。しかしPerlは,「Only perl can parse Perl」,つまり「Perlをパースできるのはperlだけ!」という格言(?)が示す複雑かつ動的な文法が災いして,Perlで書かれたプログラムを解析してトークンに分解するのは無理,すなわち静的解析は不可能という見方が長らく続いていました。

PPIの登場

しかし,2002年ごろからAdam Kennedyさんを中心としてPPIと呼ばれるPerlの総合的な解析器(ざっくり言うとPerlで記述されたトークナイザとパーサ)が開発され,Perlにおける静的解析の分野に一筋の光が射しました。現在,Perlの静的解析周りの多くのツールがPPIを解析器として利用しています。

最近の静的解析を取り巻く状況

最近では,五嶋壮晃さんが中心となり2012年ごろから開発している,C++製で高速に動作するPerlのトークナイザおよびパーサであるCompiler::LexerCompiler::Parserなども台頭してきており,Perlの静的解析を取り巻く状況は非常におもしろいものとなっています。

これらにまつわる詳細については次節で説明します。

著者プロフィール

川上大喜(かわかみたいき)

北海道函館市出身。高専卒業後,大学に編入。現在,大学院生業務をこなしつつ某企業でパートタイムエンジニアとして活動中。ソフトウェアのテストやCIといった,ソフトウェアの品質担保に関する話題に強い興味を持っている。

Twitter:@moznion
Web:http://moznion.hatenadiary.com/

コメント

コメントの記入