(57)【要約】【課題】ソースコードからリソース捕捉関数とリソース解放関数のペアを抽出する。【解決手段】ソースコードを解析して、ソースコードに含まれる関数の一覧を作成する。関数の一覧に含まれる関数のうち２つの関数を、第１の関数および第２の関数とする。（ａ）ソースコード中、第１の関数が呼び出された後の経路各々が、（１）第１の関数の返却値を引数として第２の関数が呼び出されている、（２）第１の関数の返却値が使用されていない、（３）第１の関数の返却値が使用されているが、第１の関数の返却値を引数として第２の関数が呼び出されていない、という３つの条件のうちいずれか１つを満足し、かつ、（ｂ）条件（３）を満足する経路の数が、条件（１）、（２）、（３）それぞれを満足する経路の数の合計に占める割合が所定の割合以下である場合に、第１の関数および第２の関数のペアを、リソース捕捉関数およびリソース解放関数のペアとして抽出する。【選択図】図１
2017037387.tif 000002
【特許請求の範囲】
【請求項１】
ソースコードを解析して、ソースコードに含まれる関数の一覧を作成する解析部と、
前記関数の一覧に含まれる関数のうち２つの関数を、第１の関数および第２の関数とし、（ａ）前記ソースコード中、前記第１の関数が呼び出された後の経路各々が、（１）前記第１の関数の返却値を引数として前記第２の関数が呼び出されている、（２）前記第１の関数の返却値が使用されていない、（３）前記第１の関数の返却値が使用されているが、前記第１の関数の返却値を引数として前記第２の関数が呼び出されていない、という３つの条件のうちいずれか１つを満足し、かつ、（ｂ）前記条件（３）を満足する経路の数が、前記条件（１）、（２）、（３）それぞれを満足する経路の数の合計に占める割合が所定の割合以下である場合に、前記第１の関数および前記第２の関数のペアを、リソース捕捉関数およびリソース解放関数のペアとして抽出する抽出部と、
を備えることを特徴とするプログラム解析装置。
【請求項２】
前記条件（ａ）および（ｂ）が満足される場合に、前記条件（３）を満足する経路を、リソース解放漏れの誤りを含む可能性がある経路として検出する検出部をさらに備えることを特徴とする請求項１に記載のプログラム解析装置。
【請求項３】
前記解析部はさらに、前記ソースコードの制御フローグラフを作成し、
前記抽出部は、｛前記条件（３）を満足する経路数／（前記条件（１）を満足する経路数＋前記条件（２）を満足する経路数＋前記条件（３）を満足する経路数）｝を算出するに当たり、
前記制御フローグラフにおいて、前記第１の関数が呼び出された後の経路のうち前記条件（３）を満たす複数の経路上で、（ａ）前記第１の関数の返却値ｒの値が文中で読み取られ、かつ、他の変数ｗに値が代入される結果として、前記返却値ｒと前記他の変数ｗとがエイリアスの関係にならない、（ｂ）前記返却値ｒが関数の引数の中で参照される、（ｃ）前記返却値ｒが条件判定の条件式の中で参照される、という３つの条件のうちいずれか１つを満足するノードを特定し、当該ノードよりも後のノードを削除し、
前記ノードを削除した後の前記複数の経路各々が含むノードが同一となった場合は、前記複数の経路を１つと数えることで、前記条件（３）を満足する経路数を算出することを特徴とする請求項１に記載のプログラム解析装置。
【請求項４】
ソースコードを解析して、当該ソースコードに含まれる関数の一覧を作成する解析工程と、
前記関数の一覧に含まれる関数のうち２つの関数を、第１の関数および第２の関数とし、（ａ）前記ソースコード中、前記第１の関数が呼び出された後の経路各々が、（１）前記第１の関数の返却値を引数として前記第２の関数が呼び出されている、（２）前記第１の関数の返却値が使用されていない、（３）前記第１の関数の返却値が使用されているが、前記第１の関数の返却値を引数として前記第２の関数が呼び出されていない、という３つの条件のうちいずれか１つを満足し、かつ、（ｂ）前記条件（３）を満足する経路の数が、前記条件（１）、（２）、（３）それぞれを満足する経路の数の合計に占める割合が所定の割合以下である場合に、前記第１の関数および前記第２の関数のペアを、リソース捕捉関数およびリソース解放関数のペアとして抽出する抽出工程と、
をコンピュータが実行することを特徴とするプログラム解析方法。
【請求項５】
前記コンピュータはさらに、前記条件（ａ）および（ｂ）が満足される場合に、前記条件（３）を満足する経路を、リソース解放漏れの誤りを含む可能性がある経路として検出する検出工程を実行することを特徴とする請求項４に記載のプログラム解析方法。
【請求項６】
コンピュータを請求項１〜３のいずれか１項に記載のプログラム解析装置として機能させるためのプログラム解析プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラム解析装置、プログラム解析方法およびプログラム解析プログラムに関する。
【背景技術】
【０００２】
プログラム作成時に誤りを検出する技術が研究されている。そのひとつに、静的コード解析によりプログラムの誤りの可能性のある箇所を検出する技術がある。
【０００３】
静的コード解析による誤り検出技術の例として、Ｃプログラムを対象としたｍａｌｌｏｃ関数で確保したメモリがｆｒｅｅ関数で解放されていない箇所を検出する技術、ｍａｌｌｏｃ関数で確保した未初期化メモリを参照している箇所を検出する技術などがある（例えば非特許文献１参照）。
【先行技術文献】
【非特許文献】
【０００４】
【非特許文献１】W.  R.  Bush,  J.  D.  Pincus,  and  D.  J.  Sielaff,  “A  static  analyzer  for  finding  dynamic  programming  errors”,  Software  Practice  and  Experience,  2000年,  vol.  30,  No.  7,  pp.  775-802
【発明の概要】
【発明が解決しようとする課題】
【０００５】
ところで、プログラム作成者は、ｍａｌｌｏｃ関数やｆｒｅｅ関数などの一般的なリソース捕捉関数、リソース解放関数を使用するだけでなく、独自のリソース捕捉関数とリソース解放関数を用いてプログラムを作成することがある。
【０００６】
既存の静的コード解析ツールは、プログラム作成者が独自のリソース捕捉関数とリソース解放関数を使用してプログラムを作成した場合でも、ｍａｌｌｏｃ関数やｆｒｅｅ関数などの一般的な関数で捕捉したリソースの未初期化参照やリソース解放漏れは検出できる。しかし、既存の静的コード解析ツールでは、プログラム作成者独自のリソース捕捉関数を用いて捕捉されたリソースの未初期化参照やリソース解放漏れを検出することができなかった。
【０００７】
そこで、既存の静的コード解析ツールに、プログラム作成者独自のリソース捕捉関数やリソース解放関数を登録し、ｍａｌｌｏｃ関数やｆｒｅｅ関数と同様に静的コード解析をすることも考えられる。静的コード解析ツールに、プログラム作成者が独自に定義した関数を検出する機能を追加することで、プログラム作成者独自のリソース捕捉関数を用いて捕捉されたリソースの未初期化参照やリソース解放漏れも検出できると予想される。
【０００８】
プログラム作成者独自の関数を静的コード解析ツールに登録するためには、静的コード解析ツールのユーザがリソース捕捉・解放関数を管理し登録することが必要となる。しかし、そのためには、静的コード解析を行うために、ユーザがリソース捕捉・解放関数を管理しておき、かつ、ツールに誤りなく登録する手間がかかり、利便性が悪い。
【０００９】
そこで、プログラム作成者独自の関数を、プログラムから自動的に検出する技術を開発することが考えられる。しかし、作成されたプログラム自体に解放漏れを含むことが予想される。このため、リソース捕捉関数とリソース解放関数のように対にして使用される関数が常に対になっていることを前提として検出を行うと、検出漏れが発生する可能性がある。
【００１０】
開示の実施形態は、上記に鑑みてなされたものであり、ソースコードからリソース捕捉関数とリソース解放関数のペアを抽出することを目的とする。
【課題を解決するための手段】
【００１１】
開示するプログラム解析装置は、ソースコードを解析して、ソースコードに含まれる関数の一覧を作成する解析部と、関数の一覧に含まれる関数のうち２つの関数を、第１の関数および第２の関数とし、（ａ）ソースコード中、第１の関数が呼び出された後の経路各々が、（１）第１の関数の返却値を引数として第２の関数が呼び出されている、（２）第１の関数の返却値が使用されていない、（３）第１の関数の返却値が使用されているが、第１の関数の返却値を引数として第２の関数が呼び出されていない、という３つの条件のうちいずれか１つを満足し、かつ、（ｂ）条件（３）を満足する経路の数が、条件（１）、（２）、（３）それぞれを満足する経路の数の合計に占める割合が所定の割合以下である場合に、第１の関数および第２の関数のペアを、リソース捕捉関数およびリソース解放関数のペアとして抽出する抽出部と、を備える。
【発明の効果】
【００１２】
開示するプログラム解析装置、プログラム解析方法およびプログラム解析プログラムは、ソースコードからリソース捕捉関数とリソース解放関数のペアを抽出するという効果を奏する。
【図面の簡単な説明】
【００１３】
【図１】図１は、本実施の形態におけるプログラム解析装置の構成の一例を示すブロック図である。
【図２】図２は、本実施の形態におけるプログラム解析処理の流れの一例を示すフローチャートである。
【図３】図３は、ソースコードの解析処理の流れの一例を示すフローチャートである。
【図４】図４は、プログラム解析装置の解析対象であるソースコードの一例を示す図である。
【図５】図５は、図４のソースコードから作成したサブルーチン展開コードの例を示す図である。
【図６】図６は、図５のサブルーチン展開コードから抽出した関数一覧を示す図である。
【図７】図７は、図５のサブルーチン展開コードから作成した制御フローグラフである。
【図８Ａ】図８Ａは、図５のサブルーチン展開コードの解析結果を示す図である。
【図８Ｂ】図８Ｂは、図８Ａに続く、図５のサブルーチン展開コードの解析結果を示す図である。
【図８Ｃ】図８Ｃは、図８Ｂに続く、図５のサブルーチン展開コードの解析結果を示す図である。
【図９】図９は、リソース捕捉関数とリソース解放関数とリソース格納変数の出現パタンの一例を説明する図である。
【図１０】図１０は、リソース捕捉関数とリソース解放関数の出現パタンの一例を制御フローグラフで表した図である。
【図１１】図１１は、リソース解放漏れ経路を含むソースコードの一例を制御フローグラフで表した図である。
【図１２】図１２は、本実施の形態において、リソース捕捉関数呼出し後の経路を抽出する処理について説明するための図である。
【図１３】図１３は、本実施の形態において、リソース解放漏れ候補経路の全経路に対する割合を算出する処理について説明するための第１の図である。
【図１４】図１４は、本実施の形態において、リソース解放漏れ候補経路の全経路に対する割合を算出する処理について説明するための第２の図である。
【図１５】図１５は、リソース捕捉関数とリソース解放関数の抽出処理の流れを示すフローチャートである。
【図１６】図１６は、２つの関数と変数がリソース捕捉関数、リソース解放関数、およびリソース格納変数の出現パタンに当てはまるか否かを調べる処理の流れを示すフローチャートである。
【図１７】図１７は、開示の技術にかかるプログラム解析プログラムによる情報処理がコンピュータを用いて具体的に実現されることを示す図である。
【発明を実施するための形態】
【００１４】
以下に、開示するプログラム解析装置、プログラム解析方法およびプログラム解析プログラムの実施形態を図面に基づいて詳細に説明する。なお、この実施形態によりこの発明が限定されるものではない。また、各実施形態は適宜組み合わせることができる。
【００１５】
図１は、本実施の形態に係るプログラム解析装置１の構成の一例を示すブロック図である。プログラム解析装置１は、ソースコードの入力を受けてソースコードを解析し、リソース捕捉関数とリソース解放関数のペアを抽出する。また、プログラム解析装置１は、入力されたソースコード中、リソース解放漏れの誤りを含む可能性がある経路を検出する。
【００１６】
図１に示すプログラム解析装置１は、入力部１０と、制御部２０と、記憶部３０と、出力部４０と、を備える。
【００１７】
入力部１０は、情報の入力を受け付ける処理部である。たとえば、入力部１０は、プログラム解析装置１の解析対象となるソースコードの入力を受け付ける。後述する例においては、Ｃ言語のソースコードを説明する。ただし、本実施の形態のプログラム解析方法は、Ｃ言語のみに限らず他のプログラミング言語にも適用できる。
【００１８】
制御部２０は、プログラム解析装置１を制御する。制御部２０はたとえば、ＣＰＵ（Central  Processing  Unit）、ＭＰＵ（Micro  Processing  Unit）や、ＡＳＩＣ（Application  Specific  Integrated  Circuit）等で構成することができる。制御部２０は、解析部２１、抽出部２２、および検出部２３を備える。
【００１９】
解析部２１は、入力部１０が入力を受付けたソースコードを解析する。具体的には、解析部２１は、ソースコード中でサブルーチン呼出し（関数呼出し）している箇所に、そのサブルーチン（関数）の定義コードを書き足してサブルーチン展開コードを作成し、サブルーチン展開コードの各行について、関数呼出しをしているか、関数の返却値を格納する変数はなにか、関数の引数はなにか、分岐しているか、分岐後の合流地点はどこか、利用されている変数はなにか、などの情報を解析する。また、解析部２１は、サブルーチン展開コードの各行をノードとして制御フローグラフを作成する。
【００２０】
抽出部２２は、解析部２１の解析結果を基に、リソース捕捉関数とリソース解放関数のペアを抽出する。具体的には、ソースコード中の２つの異なる関数について、所定の条件（後述）を満たすか否かを調べ、所定の条件を満足する２つの異なる関数を、ソースコードの中からリソース捕捉関数とリソース解放関数のペアとして抽出する。所定の条件は、リソース捕捉関数とリソース解放関数が使われる一般的なパタンと、リソース捕捉関数とリソース解放関数の記述の際に生じやすい誤りと、を考慮して設定する。
【００２１】
たとえば、リソース捕捉関数とリソース解放関数が使われる一般的なパタンとしては、リソース捕捉関数が呼び出されて、その結果がリソース格納変数に代入され、リソース格納変数を介してリソースが使われた後で、リソース解放関数が呼び出されるパタンがある。この場合、リソース捕捉関数が呼び出された後にリソース格納変数が参照される。リソース解放関数より後にリソース格納変数が参照されることもない。また、リソース捕捉関数が呼び出された後にリソース解放関数が呼び出されるが、リソース解放関数が２回以上呼び出されることはない。また、リソース捕捉関数およびリソース解放関数のそれぞれの記述においては、通常両者のエラー処理が記述される場合がある。
【００２２】
またたとえば、リソース捕捉関数とリソース解放関数の記述の際に生じやすい誤りとして、リソース解放漏れの誤りが考えられる。リソース解放漏れとは、リソース捕捉関数が呼び出された後に、リソース格納変数が参照されたが、その後リソース解放関数が呼び出されないままプログラムが終了している場合である。リソース捕捉関数の呼び出し後に実行経路が多数に分岐する場合等に、リソース解放漏れの誤りが生じやすい。後述する実施例では、リソース解放漏れの誤りの可能性を加味して、上記所定の条件を設定し、リソース捕捉関数とリソース解放関数のペアを抽出する。
【００２３】
検出部２３は、抽出部２２の処理結果に基づき、ソースコードからリソース解放漏れの誤りの可能性がある経路（以下、リソース解放漏れ候補経路とも呼ぶ。）を検出する。
【００２４】
記憶部３０は、プログラム解析装置１における各部の処理に使用する情報や、各部の処理によって生成される情報を記憶する。記憶部３０はたとえば、ハードディスク、光ディスク等の記憶装置でもよい。また、記憶部３０は、ＲＡＭ（Random  Access  Memory）やフラッシュメモリ等の半導体メモリであってもよい。
【００２５】
記憶部３０は、ソースコード記憶部３１と、サブルーチン展開コード記憶部３２と、関数一覧記憶部３３と、制御フローグラフ記憶部３４と、解析結果記憶部３５と、関数ペア集合記憶部３６と、を備える。
【００２６】
ソースコード記憶部３１は、入力部１０が入力を受付けたソースコードを記憶する。サブルーチン展開コード記憶部３２は、解析部２１がソースコードから作成したサブルーチン展開コードを記憶する。関数一覧記憶部３３は、解析部２１がサブルーチン展開コードから抽出した関数一覧を記憶する。制御フローグラフ記憶部３４は、解析部２１がサブルーチン展開コードから作成した制御フローグラフを記憶する。解析結果記憶部３５は、解析部２１がサブルーチン展開コードを解析して取得した解析結果を記憶する。また、関数ペア集合記憶部３６は、抽出部２２による処理の結果得られる関数ペア集合を記憶する。なお、記憶部３０の各部に記憶されるソースコード、サブルーチン展開コード、関数一覧、制御フローグラフ、解析結果、関数ペア集合の詳細については後述する。
【００２７】
出力部４０は、プログラム解析装置１による処理の結果、取得される情報を出力する。出力部４０はたとえば、抽出部２２が抽出するリソース捕捉関数とリソース解放関数のペアを、視認可能な形式で出力する。また、出力部４０はたとえば、検出部２３が検出するリソース解放漏れ候補経路を、視認可能な形式で出力する。出力部４０は、モニタ等の表示部またはプリンタ等と接続され表示部またはプリンタ等に情報を出力するように構成してもよく、出力部４０が表示部またはプリンタ等を備えるように構成してもよい。
【００２８】
（プログラム解析処理の流れの一例）
次に、本実施の形態におけるプログラム解析装置１の動作について説明する。
【００２９】
図２は、本実施の形態におけるプログラム解析処理の流れの一例を示すフローチャートである。
【００３０】
入力部１０は、解析対象のソースコードの入力を受け付ける（ステップＳ１）。
【００３１】
解析部２１は、ソースコードを解析する（ソースコード解析処理、ステップＳ２）。ソースコードの解析処理の詳細については後述する。
【００３２】
抽出部２２は、ソースコードの解析結果を基に、リソース捕捉関数とリソース解放関数のペアをソースコードから抽出する（関数ペア抽出処理、ステップＳ３）。リソース捕捉関数とリソース解放関数の抽出処理の詳細については後述する。
【００３３】
そして、検出部２３は、抽出部２２による処理結果に基づき、リソース解放漏れ候補経路を検出する（ステップＳ４）。リソース解放漏れ候補経路の検出処理の詳細については、上記抽出処理と併せて後述する。
【００３４】
出力部４０は、抽出部２２が抽出したリソース捕捉関数とリソース解放関数のペアや、検出部２３が検出したリソース解放漏れ候補経路を出力する（ステップＳ５）。
【００３５】
これでプログラム解析装置１によるプログラム解析処理が終了する。
【００３６】
（ソースコードの解析処理の流れの一例）
次に、ソースコードの解析処理（図２のステップＳ２に対応）について説明する。
【００３７】
図３は、ソースコードの解析処理の流れの一例を示すフローチャートである。図４は、プログラム解析装置の解析対象であるソースコードの一例を示す図である。以下では、図４に示すソースコードを入力した具体例とともにソースコードの解析処理を説明する。
【００３８】
解析部２１は、入力部１０が入力したソースコードからサブルーチン展開コードを作成する（ステップＳ２１）。作成されたサブルーチン展開コードは、サブルーチン展開コード記憶部３２に記憶される。図５に、図４のソースコードから作成したサブルーチン展開コードの例を示す。図５の例では、解析部２１は、ｍａｉｎ関数から呼び出されているｆｉｎｉｓｈ関数とａｂｏｒｔ＿ｐｒｏｇｒａｍ関数のソースコードを呼び出した箇所の下に展開して追記している。解析部２１は、さらにｆｉｎｉｓｈ関数から呼び出されているａｂｏｒｔ＿ｐｒｏｇｒａｍ関数も展開して追記している。具体的には、符号１０１Ａ，１０１Ｂで示す箇所にａｂｏｒｔ＿ｐｒｏｇｒａｍ関数を展開し、符号１０２で示す箇所にｆｉｎｉｓｈ関数を展開した。符号１０１Ｂで示す箇所に展開したａｂｏｒｔ＿ｐｒｏｇｒａｍ関数はｆｉｎｉｓｈ関数から呼び出されたものである。
【００３９】
サブルーチン展開コードでは、関数を展開した箇所の行番号として、呼出し元の行番号に元々のソースコードの行番号を付与した行番号（以下、「コールスタック付き行番号」と称する。）を付与する。例えば、符号１０１Ａで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数は、ｍａｉｎ関数の９行目で呼び出されており、ａｂｏｒｔ＿ｐｒｏｇｒａｍ関数は、図４のソースコードの２５−２７行目に記述されているので、９行目に展開したａｂｏｒｔ＿ｐｒｏｇｒａｍ関数の各行に行番号９−２５，９−２６，９−２７を付与する。別の例では、符号１０２で示した箇所のｆｉｎｉｓｈ関数はｍａｉｎ関数の１３行目で呼び出されており、符号１０１Ｂで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数はｆｉｎｉｓｈ関数の２４行目で呼び出されているので、符号１０１Ｂで示した箇所のａｂｏｒｔ＿ｐｒｏｇｒａｍ関数の各行に行番号１３−２４−２５，１３−２４−２６，１３−２４−２７を付与する。なお、サブルーチン（関数）の定義が得られない場合は定義コードは書き足さない。
【００４０】
続いて、解析部２１は、サブルーチン展開コードから関数を抽出して関数一覧を作成する（ステップＳ２２）。作成した関数一覧は、関数一覧記憶部３３に記憶される。図６に、図５のサブルーチン展開コードから抽出した関数一覧を示す。解析部２１は、抽出した関数に関数ＩＤを付与する。図６の例に示すように、関数一覧記憶部３３は、関数ＩＤに対応付けて各関数名を記憶する。
【００４１】
続いて、解析部２１は、サブルーチン展開コードから制御フローグラフを作成する（ステップＳ２３）。作成した制御フローグラフは、制御フローグラフ記憶部３４に記憶される。制御フローグラフは、プログラムを実行したときの制御の流れを有向グラフで示したものである。図７に、図５のサブルーチン展開コードから作成した制御フローグラフを示す。本実施の形態では、コールスタック付き行番号をノードとし、呼び出された関数の内部に制御の流れを追うステップイン接続と、関数の内部に制御の流れを追わないステップオーバー接続の２つのエッジを付与した。図７の点線で示すエッジがステップイン接続を示し、実線で示すエッジがステップオーバー接続を示す。なお、本実施の形態では、プログラムの制御構造のひとつであるループは考慮せずに、ループは、１回だけ実行されるものとみなして解析する。
【００４２】
そして、解析部２１は、サブルーチン展開コードを解析する（ステップＳ２４）。図８Ａ〜８Ｃは、解析部２１によるサブルーチン展開コードの解析結果を示す図である。解析結果は、解析結果記憶部３５に記憶される。本実施の形態では、サブルーチン展開コードの行ごとに、エイリアス集合、関数呼出し、関数ＩＤ、関数返却値格納変数、引数、分岐、合流行番号、および効果有り参照されている変数を抽出する。
【００４３】
エイリアス集合は、ソースコードに現れる変数のエイリアス組の集合である。本実施の形態では、該当行を実行後の時点でのエイリアス集合を求めている。例えば、４行目のｃｍｄと５行目のｃｍｄは同じものであるので、行番号と変数名をペアにしたフロー依存変数（４，ｃｍｄ），（５，ｃｍｄ）をエイリアス集合に加えている。エイリアス集合の要素は、変数名が異なるときも同じものとみなすことができる。本実施の形態で想定するエイリアス解析はフローセンシティブエイリアス解析であり、ソースコードの行によって変数の関係性が変わることを考慮するものである。なお、フロー依存変数とは、変数名ｒと変数が出現したコールスタック付き行番号ｋの組（ｋ，ｒ）である。
【００４４】
関数呼出しは、当該行で関数を呼び出しているか否かを示す。図８Ａ〜図８Ｃの例では、関数を呼び出している場合は「関数呼出し」の欄に「ｙ」が記載される。関数を呼び出しているときは、呼び出している関数のＩＤ、呼び出している関数の返却値を格納する変数、および関数の引数を記載する。ソースコード上で関数に渡されている引数がアドレス演算子（＆）や間接演算子（＊）で修飾されている変数の場合は、これらの演算子を外した変数も解析結果の引数に記載する。なぜならば、アドレス演算子や間接演算子で修飾された変数が参照される前に、アドレス演算子や間接演算子で修飾されていない変数の値が参照されるからである。例えば、ソースコード上で関数に渡されている引数が＆ａの場合は、解析結果の因数の項目には、＆ａとａを記載する。別の例では、ソースコード上で関数に渡されている引数が＊＊ａの場合は、解析結果の引数の項目には、＊＊ａとともに＊ａとａとを記載する。
【００４５】
分岐は、当該行が分岐であるか否かを示す。図８Ａ〜図８Ｃの例では、分岐である場合には「分岐」の欄に「ｙ」を記載している。分岐があるときは分岐したルートの合流先を合流行番号に記載する。ｉｆ文の分岐では、ｔｈｅｎ節とｅｌｓｅ節に実行経路が分岐するが、ｔｈｅｎ節とｅｌｓｅ節の後の行が合流先となる。
【００４６】
効果有り参照されている変数は、当該行で実質的に使われている変数を記載する。より具体的には、変数ｖが効果有り参照されるとは、次に示すいずれかの条件を満たす場合であると定義する。
【００４７】
（１）変数ｖの値が読み取られ、かつ、別の変数ｗに値が代入され、その結果、変数ｖと変数ｗがエイリアスの関係にならない
（２）変数ｖが関数の引数として参照される
（３）変数ｖが条件判定文の条件式の中で参照される
【００４８】
以下、効果有り参照されている変数の具体例を説明する。たとえば、ａ＝ｖと記載された行を考えると、この行を実行した結果、変数ａは変数ｖのエイリアスになるので、この行では変数ｖは効果有り参照されていない。別の例で、ａ＝ｖ＋１が記載された行を考えると、変数ｖの値が読み取られ、かつ、変数ａに値がセットされ、その結果、変数ａと変数ｖはエイリアスの関係にならないので、この行では変数ｖは効果有り参照されている。さらに、この行の変数ａについて考えると、変数ａの値は参照されていないので、変数ａは効果有り参照されていない。
【００４９】
また別の例で、＊ｖ＝ａ＋１が記載された行を考えると、変数ｖの値が参照され、デリファレンスされて変数＊ｖに値が格納されていて、その結果、変数ｖと変数＊ｖはエイリアスの関係にならないので、変数ｖは効果有り参照されている。さらに別の例で、ａ＝＆ｖが記載された行を考えると、変数ｖのアドレスは参照されているが変数ｖの値は参照されていないので、変数ｖは効果有り参照されていない。
【００５０】
条件式の中で参照される例を挙げると、例えばｉｆ（ｖ）｛・・・｝が記載された行では、条件判定文の条件式の中で変数ｖの値が参照されているので、変数ｖは効果有り参照されている。
【００５１】
図５のソースコードの例では、例えば、５行目のｃｍｄ＝＝ＳＥＮＤ＿ＦＡＸ＿ＣＭＤは、変数ｃｍｄが条件判定文の条件式で参照されている。また例えば、６行目のｒｓｃ＝ｍｅｍｐｏｏｌ＿ａｌｌｏｃ（ｐｏｏｌ）は、関数の引数として変数ｐｏｏｌが参照されている。また、７行目のａ＿ｒｓｃ＝ｒｓｃは、ｒｓｃのエイリアスが作られているものの、ａ＿ｒｓｃに値をセットした結果、ａ＿ｒｓｃはｒｓｃのエイリアスになっているので、ｒｓｃは効果有り参照されていないことになる。
【００５２】
(リソース捕捉関数とリソース解放関数の抽出処理)
次に、リソース捕捉関数とリソース解放関数の抽出処理（図２のステップＳ３に対応）について説明する。まず、抽出処理の前提として、リソース捕捉関数とリソース解放関数の一般的出現パタンと、ソースコード上のリソース解放漏れについて説明する。
【００５３】
（リソース捕捉関数とリソース解放関数の出現パタン）
ソースコード中の一般的なリソース捕捉関数と一般的なリソース解放関数の出現パタンとしては、例えば最もシンプルなパタンとして、リソース捕捉関数の返却値を格納する変数（リソース格納変数）が指定されてリソース捕捉関数が呼び出された後、リソース格納変数が指示するリソースが使用され、その後リソース解放関数が１回だけ呼び出されるパタンがある。リソース格納変数は、リソース捕捉関数の前とリソース解放関数の後に使用されることはない。このような出現パタンに当てはまる２つの関数はリソース捕捉関数とリソース解放関数の可能性があると推定できる。
【００５４】
図９は、リソース捕捉関数とリソース解放関数とリソース格納変数の出現パタンの一例を説明する図である。図９に示すパタンは、リソース捕捉関数の後にエラー処理があり、リソース解放関数の後にエラー処理があるパタンである。リソース捕捉関数の後のエラー処理内では、リソース格納変数が参照されることはなく、リソース解放関数が呼び出されずに処理を抜ける。また、リソース解放関数の後のエラー処理内では、ログ出力などでリソース格納変数が参照されることがあるが、エラー処理を抜けた後にリソース格納変数が参照されることはない。
【００５５】
図１０は、リソース捕捉関数とリソース解放関数の出現パタンの一例を制御フローグラフで表した図である。図１０の制御フローグラフは概ね、図９に示すリソース捕捉関数とリソース解放関数が出現するパタンに対応する。図１０の例では、ノード１を経てノード２においてリソース捕捉関数が呼び出される。そして、リソース捕捉が失敗したか否かのエラー判定が、ノード３において実行される。リソース捕捉が失敗した場合、ノード４、５に進んでエラー処理が実行される。エラー処理の場合の捕捉エラー経路とその後に続く経路においては、捕捉に失敗したリソースは使用されない。他方、ノード３においてリソース捕捉に成功したと判定した場合、ノード６，７の処理に進む。図１０の例では、処理が分岐してノード８、１３の二つの経路に進む。ノード６，７，８，１３において捕捉したリソースを利用する処理が実行される。その後、ノード９，１４においてリソース解放関数が呼び出されて、分岐したそれぞれの経路上でリソースが解放される。さらに、ノード１４の後、ノード１５においてエラー判定が実行され、リソース解放に成功した場合、ノード１６に進む。他方、リソース解放に失敗した場合、ノード１７に進み、その後、ノード１６に合流する。そして分岐した経路はノード１０において合流し、さらに、捕捉エラー経路がノード１１で合流して、ノード１２に進む。リソースが解放された後の、ノード１０，１１，１２，１６においては、リソースは使用されない。このように、リソース捕捉関数の呼び出しとリソース解放関数の呼び出し、およびそれぞれのエラー処理を含む処理の流れは、図１０のような制御フローグラフで表すことができる。
【００５６】
（リソース解放漏れの可能性）
ところで、ソースコードにおいて、リソース捕捉関数とリソース解放関数とが常に図９および図１０に示すような出現パタンに当てはまると推定して抽出処理を行ったとすると、ソースコードにリソース解放漏れがある場合、正しい抽出結果を得ることができない。
【００５７】
リソース解放漏れとは、リソース捕捉関数によって捕捉したリソースを使用したのち、リソース解放関数によってリソースを解放することなく放置しているソースコードの状態である。たとえば、図１０の例のようにリソース捕捉関数によりリソースを補足した後、処理が複数に分岐する場合がある。このような場合、プログラム作成者が、プログラムの流れの全体像の把握を誤り、リソース解放関数を呼び出すべき箇所にリソース解放関数を記述し忘れることがある。すると、リソース捕捉関数とリソース解放関数のペアの出現パタンが図９の出現パタンに適合しなくなる。リソース解放漏れはプログラム作成において発生しやすい誤りである。このため、仮に、プログラム解析処理において、図９のような一般的な出現パタンに適合するリソース捕捉関数とリソース解放関数のペアのみ抽出した場合、抽出漏れが発生すると考えられる。
【００５８】
（リソース解放漏れの可能性を加味したアルゴリズム）
そこで、本実施の形態においては、リソース解放漏れの誤りを含むソースコードからもリソース捕捉関数とリソース解放関数のペアをより正確に抽出することができるよう、アルゴリズムを組み立てる。具体的には、本実施の形態では、リソース捕捉関数の呼び出し後の全経路が、以下の条件（１）から（３）のいずれかにあてはまるものと推定する。
（１）経路上で、捕捉したリソースをリソース解放関数により１度だけ解放している。
（２）経路上で、リソースを使用していない（捕捉エラー処理の場合）。
（３）経路上で、リソースを使用しているが解放しない（リソース解放漏れの場合）。
そして、条件（３）に当てはまる経路の数が、リソース捕捉関数の呼び出し後の全経路数のうち所定の割合以下であるものと推定する。本実施の形態では、この推定に基づいてアルゴリズムを組み立て、ソースコードに含まれる関数の中から、リソース捕捉関数とリソース解放関数のペアを抽出する。
【００５９】
上記推定に基づき、本実施の形態においては、以下の条件（ａ）および（ｂ）の双方に当てはまる第１の関数ｆと第２の関数ｇのペアを、リソース捕捉関数とリソース解放関数のペアとして抽出する。
（ａ）第１の関数ｆの呼び出し後の全経路が条件（１），（２），（３）のいずれかに該当する。
（１）経路上で、第１の関数ｆの返却値ｒを引数として第２の関数ｇを１度だけ呼び出している。
（２）経路上で、第１の関数ｆの返却値ｒを使用していない。
（３）経路上で、第１の関数ｆの返却値ｒを使用しているが、第１の関数ｆの返却値ｒを引数として第２の関数ｇを呼び出していない。
（ｂ）条件（３）に該当する経路が、全経路中に占める割合は、所定の割合ｅ以下である。
【００６０】
上記推定に基づく本実施の形態の抽出処理についてさらに図１１〜図１４を参照して説明する。図１１は、リソース解放漏れ経路を含むソースコードの一例を制御フローグラフで表した図である。図１２は、本実施の形態において、リソース捕捉関数呼出し後の経路を抽出する処理について説明するための図である。図１３及び図１４はそれぞれ、本実施の形態において、リソース解放漏れ候補経路の全経路に対する割合を算出する処理について説明するための第１の図および第２の図である。
【００６１】
図１１の例では、処理が開始した後、ノード２においてリソース捕捉関数が呼び出される（ｒ＝ｆ（））。そして、ノード３において、処理が二つに分岐する。さらに、ノード４，２２において処理が２つに分岐し、その後各経路が二つに分岐して、全部で８つの経路が形成される。分岐した経路はノード９，１８，２７，３５において合流する。また、ノード１０，１９，２８において、リソース解放関数が呼び出される（ｇ（ｒ））。しかし、ノード３６においては、リソース解放関数が呼び出されず、リソース解放漏れが発生している。この後、４つの分岐がノード１１で合流して処理が終了する。ソースコードから図１１に示すような制御フローグラフが得られた場合、上記条件（３）に当てはまる経路は、リソース捕捉関数の呼び出し後（ノード３以後）、ノード３１を経由してノード３６，１１に至る経路となる。すなわち、ノード番号で示すと、「３，２２，３１，３２，３３，３４，３５，３６、１１」の経路と、「３，２２，３１，３２，３７，３８，３５，３６，１１」の経路が条件（３）に当てはまる。なお、条件（１）〜（３）は、リソース捕捉関数の呼び出し後の経路について検討するため、ノード１，２は経路に含めない。また、図１１の例では、捕捉エラールート、解放エラールートは図示していない。
【００６２】
次に、図１２〜図１４を参照して、条件（３）に当てはまる経路の数と、リソース捕捉関数の呼び出し後の全経路数との数え方について説明する。
【００６３】
解放漏れの後の経路が多数分岐すると、分岐数に応じて解放漏れ候補経路数が多く数えられてしまう。解放漏れの数は少なくても、経路数は多くなりうる。このような性質は、解放漏れ候補経路数の全経路数に対する割合が小さいときにリソース捕捉・解放関数である確度を高いと推定する本実施形態の手法においては都合が悪い。そこで、解放漏れ候補経路数が、解放漏れの後の経路の分岐数によって左右されない経路の数え方を採用する。
【００６４】
図１２に示す制御フローグラフでは、ノード１においてリソース捕捉関数が呼び出され、ノード１０，１９，２８においてリソース解放関数が呼び出されているものとする。また、ノード９，１８，２７，３５において、リソース格納変数ｒがそれぞれの経路上で最後に効果有り参照されているものとする。
【００６５】
この場合に、図１２におけるリソース捕捉関数の呼び出し後の実行経路を全て抽出すると、実行経路集合Ｐは以下のようになる（図１２参照）。
（２，３，４，５，６，７，８，９，１０，１１）
（２，３，４，５，６，１２，１３，９，１０，１１）
（２，３，４，１４，１５，１６，１７，１８，１９，１１）
（２，３，４，１４，１５，２０，２１，１８，１９，１１）
（２，３，２２，２３，２４，２５，２６，２７，２８，１１）
（２，３，２２，２３，２４，２９，３０，２７，２８，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，３７，３８，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，３７，４０，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，４２，４３，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，４２，４４，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，３７，３８，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，３７，４０，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，４２，４３，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，４２，４４，３９，１１）
（４７，４８，１１）
【００６６】
抽出した実行経路のうち、経路上でリソース解放関数を呼出している経路すなわち上記条件（１）に該当する経路を、以下、解放実施経路と呼ぶ。解放実施経路は、１０，１９，２８のいずれかを含む経路であり、以下の６つが該当する（図１３参照）。
（２，３，４，５，６，７，８，９，１０，１１）
（２，３，４，５，６，１２，１３，９，１０，１１）
（２，３，４，１４，１５，１６，１７，１８，１９，１１）
（２，３，４，１４，１５，２０，２１，１８，１９，１１）
（２，３，２２，２３，２４，２５，２６，２７，２８，１１）
（２，３，２２，２３，２４，２９，３０，２７，２８，１１）
【００６７】
次に、抽出した実行経路のうち、経路上でリソースを使用していない経路すなわち上記条件（２）に該当する経路を、以下、捕捉失敗候補経路と呼ぶ。捕捉失敗候補経路は、以下の１つが該当する（図１３参照）。
（４７，４８，１１）
【００６８】
そして、残りの経路すなわち上記条件（３）に該当する経路を、以下、解放漏れ候補経路と呼ぶ。解放漏れ候補経路は、以下の８つが該当する（図１３参照）。
（２，３，２２，３１，３２，３３，３４，３５，３６，３７，３８，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，３７，４０，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，４２，４３，３９，１１）
（２，３，２２，３１，３２，３３，３４，３５，３６，４２，４４，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，３７，３８，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，３７，４０，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，４２，４３，３９，１１）
（２，３，２２，３１，３２，４５，４６，３５，３６，４２，４４，３９，１１）
【００６９】
次に、解放漏れ候補経路が含むノードのうち、最後にリソース格納変数すなわちリソース捕捉関数の返却値ｒを効果有り参照したノードの次のノード以降を削除する。すなわち、各経路上で、リソースを使用していない末尾部分を削除する。図１２の例では、ノード９，１８，２７，３５においてリソース格納変数が効果有り参照されている。したがって、末尾部分の削除後の各経路は、以下のようになる（図１３参照）。
（２，３，２２，３１，３２，３３，３４，３５）
（２，３，２２，３１，３２，３３，３４，３５）
（２，３，２２，３１，３２，３３，３４，３５）
（２，３，２２，３１，３２，３３，３４，３５）
（２，３，２２，３１，３２，４５，４６，３５）
（２，３，２２，３１，３２，４５，４６，３５）
（２，３，２２，３１，３２，４５，４６，３５）
（２，３，２２，３１，３２，４５，４６，３５）
【００７０】
さらに、末尾部分を削除した後の各経路のうち、同一になった経路をまとめて１経路と数える。すると、上の８つの経路は以下の２つの経路にまとめられる。同一経路をまとめた後の解放漏れ候補経路の数を、単一化後解放漏れ候補経路数と呼ぶ（図１４参照）。
（２，３，２２，３１，３２，３３，３４，３５）
（２，３，２２，３１，３２，４５，４６，３５）
【００７１】
この結果、上記条件（１）に該当する解放実施経路数は６、上記条件（２）に該当する捕捉失敗候補経路数は１、上記条件（３）に該当する単一化後解放漏れ候補経路数は２となる。そして、上記条件（３）に該当する単一化後解放漏れ候補経路数が、全経路に占める割合を、（単一化後解放漏れ候補経路数／（解放実施経路数＋捕捉失敗候補経路数＋単一化後解放漏れ候補経路数））により算出する。
【００７２】
（リソース捕捉関数とリソース解放関数の抽出処理の流れの一例）
図１５、図１６は、リソース捕捉関数とリソース解放関数の抽出処理の流れの一例を示すフローチャートである。
【００７３】
まず、抽出部２２は、リソース捕捉関数とリソース解放関数のペアを格納する関数ペア集合を空集合にする（ステップＳ３１）。
【００７４】
抽出部２２は、関数一覧から２つの関数ｆ，ｇを選択し、すべての関数の組み合わせについて以下の処理を繰り返す（ステップＳ３２）。関数一覧に含まれる関数ＩＤの集合をＦとするとｆ∈Ｆ，ｇ∈Ｆ，ｆ≠ｇである。
【００７５】
抽出部２２は、解析結果を参照し、関数ｆが呼び出されているコールスタック付き行番号ｋを挙げて行番号集合Ｋを作成する（ｋ∈Ｋ、ステップＳ３３）。
【００７６】
抽出部２２は、解析結果を参照し、行番号ｋと、行番号ｋにおいて関数ｆの返却値を格納している変数ｒと、のペアをフロー依存変数（ｋ，ｒ）としてフロー依存変数集合Ｒを作成する（ステップＳ３４）。この処理により、関数ｆが呼び出されている行番号ｋとリソース格納変数の候補である変数ｒをペアとしたフロー依存変数集合Ｒ＝｛（ｋ１，ｒ１），（ｋ２，ｒ２），・・・｝が作成される。
【００７７】
抽出部２２は、好適パタン数を０に設定し、解放漏れ候補経路集合Ｌ＝｛｝と設定する。そして、抽出部２２は、全てのフロー依存変数（ｋ，ｒ）∈Ｒについて、行番号ｋ以降の実行経路において、２つの関数ｆ，ｇと変数ｒの出現パタンが上記の条件（ａ）（ｂ）を満足するか否か判定する（ステップＳ３５〜Ｓ３７）。ステップＳ３６の判定結果がポジティブであるときは好適パタン数に１を加算し、ステップＳ３６において抽出されたサブ解放漏れ候補経路集合Ｌｃｕｒ（後述）を解放漏れ候補経路集合Ｌに追加する。ステップ３６における判定処理の詳細は後述する。
【００７８】
そして、全てのフロー依存変数（ｋ，ｒ）∈ＲについてステップＳ３５〜Ｓ３７の処理が終了する（ループ２、ステップＳ３７）と、抽出部２２は、ステップＳ３８の処理に進む。ステップＳ３８において、抽出部２２は、行番号集合Ｋに含まれる行番号の数｜Ｋ｜と、フロー依存変数集合Ｒに含まれるフロー依存変数の数｜Ｒ｜とが一致し、かつ、｜Ｒ｜と好適パタン数が一致するか否かを判定する。抽出部２２は、判定結果がポジティブであるときは、関数ペア（ｆ，ｇ）と、解放漏れ候補経路集合Ｌと、を関数ペア集合に追加する（ステップＳ３８）。すなわち、抽出部２２は、｜Ｋ｜と、｜Ｒ｜と、好適パタン数とが一致すると判定した場合、関数ｆ，ｇはリソース捕捉関数とリソース解放関数であると判定し、解放漏れ候補経路集合Ｌはリソース解放漏れの誤りの可能性がある経路の集合であると判定する。なお、抽出部２２は、フロー依存変数の数｜Ｒ｜と好適パタン数が一致するときはすべてのフロー依存変数の判定結果がポジティブであるので、関数ペア（ｆ，ｇ）を関数ペア集合に追加する。ただし、行番号ｋの数｜Ｋ｜とフロー依存変数の数｜Ｒ｜が一致しない場合は、ソースコード中に関数ｆの返却値が変数に格納されない箇所があり、関数ｆはリソース捕捉関数ではないと考えられるので、抽出部２２は、関数ペア（ｆ，ｇ）を関数ペア集合に追加しない。
【００７９】
抽出部２２は、全ての関数ペア（ｆ，ｇ），ｆ∈Ｆ，ｇ∈Ｆ，ｆ≠ｇについて、ステップＳ３３〜Ｓ３８の処理を行う（ループ１、ステップＳ３９）。
【００８０】
以上の処理により、リソース捕捉関数とリソース解放関数のペアである可能性の関数ペアと、リソース解放漏れの誤りを含む可能性がある経路の集合と、が関数ペア集合に格納される。関数ペア集合は、関数ペア集合記憶部３６に記憶される。
【００８１】
続いて、図１５に示すループ２（ステップＳ３５〜Ｓ３７）における、２つの関数ｆ，ｇと変数ｒの出現パタンが上記の条件（ａ）（ｂ）を満足するか否かを判定する処理の詳細について説明する。
【００８２】
図１６は、２つの関数ｆ，ｇと変数ｒがリソース捕捉関数、リソース解放関数、およびリソース格納変数の出現パタンに当てはまるか否かを調べる処理の流れを示すフローチャートである。図１６に示す処理では、併せて解放漏れ候補経路が抽出される。図１６に示す処理では、関数ｆが呼び出された行番号ｋより後の実行経路の全てにおいて、関数ｆ，ｇと変数ｒの出現パタンが上記の条件（ａ）（ｂ）を満足するか否かを判定する。
【００８３】
抽出部２２は、制御フローグラフ記憶部３４に記憶される制御フローグラフを参照し、関数ｆが呼び出された行番号ｋより後の実行経路ｐをすべて挙げて実行経路集合Ｐを作成する（ステップＳ５１）。ここで、実行経路ｐを作成する際には、関数ｆ，ｇの呼び出しのノードについては、その次のノードはステップオーバー接続をたどったノードとする。つまり、ステップイン接続はたどらない。関数ｆ，ｇ以外の関数の呼び出しのノードについては、ステップイン接続がある場合はステップイン接続だけをたどる。そして、ステップイン接続がなければステップオーバー接続をたどる。ステップオーバー接続をたどるときに、１ノードを起点とするステップオーバー接続が複数ある場合には、接続の選び方に応じた実行経路をそれぞれ作成する。実行経路ｐは、コールスタック付き行番号の順序付き集合ｐ＝｛ｎ１，ｎ２，・・・，ｎｍ｝で表す（ｐ∈Ｐ）。
【００８４】
抽出部２２は、好適経路数、捕捉失敗候補経路数を０に設定する。また、抽出部２２は、サブ解放漏れ候補経路集合ＬｃｕｒについてＬｃｕｒ＝｛｝と設定する。好適経路数とは、実行経路集合Ｐの中で条件（１）または（２）に該当する実行経路ｐの数である。また、捕捉失敗候補経路数とは、リソース捕捉関数のエラー処理に当てはまった実行経路ｐの数である。すなわち、捕捉失敗候補経路数とは、条件（２）に該当する実行経路ｐの数である。サブ解放漏れ候補経路集合とは、ループ３の内側で、条件（３）に該当するが、条件（ａ）、（ｂ）の判定を経ていない経路の集合である。そして、抽出部２２は、全ての実行経路ｐ∈Ｐについて、以下の処理を繰り返す（ステップＳ５２）。
【００８５】
抽出部２２は、捕捉後使用区間調査フラグをｔｒｕｅに設定する（ステップＳ５３）。捕捉後使用区間調査フラグは、実行経路ｐの検査結果を示すフラグである。図１６の判定処理において、実行経路ｐが上記条件（ａ）を満足しないときは、捕捉後使用区間調査フラグにｆａｌｓｅが設定される。
【００８６】
抽出部２２は、実行経路ｐ上で、変数ｒのエイリアスを引数として関数ｇが２回以上呼び出されているか判定する（ステップＳ５４）。リソース解放関数が２回以上呼び出されることはないので、関数ｇが２回以上呼び出されている場合は（ステップＳ５４のＹｅｓ）、抽出部２２は、捕捉後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００８７】
抽出部２２は、関数ｇが２回以上呼び出されていない場合は（ステップＳ５４のＮｏ）、実行経路ｐ上で、変数ｒのエイリアスを引数として関数ｇが１回呼び出されているか判定する（ステップＳ５５）。関数ｇが１回呼び出されていない場合は（ステップＳ５５のＮｏ）、実行経路ｐはリソース捕捉関数のエラー処理の経路である可能性があるので、抽出部２２は、ステップＳ５８に進む。
【００８８】
実行経路ｐ上で関数ｇが１回呼び出されている場合（ステップＳ５５のＹｅｓ）、抽出部２２は、関数ｇが呼び出されるまでに変数ｒのエイリアスのいずれかが効果有り参照されているか判定する（ステップＳ５６）。変数ｒが効果有り参照されていない場合は（ステップＳ５６のＮｏ）、捕捉後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００８９】
なお、「変数ｒのエイリアスのいずれかが効果有り参照される」とは、具体的には、「フロー依存変数（ｋ，ｒ）のエイリアスのいずれかが効果有り参照される」という意味である。
【００９０】
ここで、ステップＳ５６の変数ｒの効果有り参照の有無判定について説明する。関数ｇは実行経路ｐのｊ番目の要素ｎｊに対応する行で呼び出されているとする。抽出部２２は、実行経路ｐの先頭の要素ｎ１からｊ−１番目の要素ｎｊ−１までのいずれかの要素において、解析結果の効果有り参照されている変数の項目に変数ｒのエイリアスのいずれかが記載されているか否かを調べる。変数ｒのエイリアスが効果有り参照されている場合はステップＳ５６の判定結果はＹｅｓとなり、変数ｒのエイリアスが効果有り参照されていない場合はステップＳ５６の判定結果はＮｏとなる。
【００９１】
関数ｇが呼び出されるまでに変数ｒのエイリアスのいずれかが効果有り参照されている場合（ステップＳ５６のＹｅｓ）、抽出部２２は、関数ｇが呼び出された後、変数ｒのエイリアスのいずれかが効果有り参照されているか判定する（ステップＳ５７）。効果有り参照されている場合は（ステップＳ５７のＹｅｓ）、抽出部２２は、捕捉後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６０）。
【００９２】
ただし、リソース解放関数のエラー処理の経路では、関数ｇが呼び出された後も変数ｒが使用される可能性があるので、リソース解放関数のエラー処理と思われる箇所は飛ばして判定する。具体的には、抽出部２２は、実行経路ｐの中で、要素ｎｊの後に、要素ｎｊと同階層で最初に出現する分岐を探し、分岐が存在する場合は実行経路ｐの中でその分岐の合流先である要素ｎｈ以降の要素をステップＳ５７の判定対象とする。また、分岐が存在しない場合や分岐の途中でプログラムが終了するなどの理由で合流先が存在しない場合は、実行経路ｐの中で要素ｎｊの後に要素ｎｊと同階層で最初に出現する要素を要素ｎｈとして要素ｎｈ以降をステップＳ５７の判定対象とする。なお、実行経路ｐの中に関数ｇが呼び出された要素ｎｊより後で要素ｎｊと同階層の要素がない場合は、ステップＳ５７の判定結果をＮｏとしてステップＳ６３に進む。
【００９３】
一方、実行経路ｐ上で関数ｇが呼び出されていない場合の（ステップＳ５５のＮｏ）、実行経路ｐがリソース捕捉関数のエラー処理の経路であるか否かの判定は、実行経路ｐで変数ｒのいずれかのエイリアスが効果有り参照されているか判定することで行う（ステップＳ５８）。具体的には、実行経路ｐの中で、先頭の要素ｎ１の後に、要素ｎ１と同階層で最初に出現する分岐を探し、分岐が存在する場合は、分岐が出現する要素をｎｈ’とし、分岐が存在しない場合は、要素ｎ１を要素ｎｈ’とする。そして、実行経路ｐの要素ｎｈ’の次の要素から最後の要素ｎｍまでのいずれかの要素に対応する箇所で、変数ｒのエイリアスのいずれかが効果有り参照されているか調べる。
【００９４】
変数ｒのエイリアスのいずれかが効果有り参照されている場合は（ステップＳ５８のＹｅｓ）、捕捉後使用区間調査フラグをｆａｌｓｅに設定する（ステップＳ６１）。そして、抽出部２２は、サブ解放漏れ候補経路集合Ｌｃｕｒに実行経路ｐを加える（Ｌｃｕｒ＝Ｌｃｕｒ∪｛ｐ｝）（ステップＳ６２）。
【００９５】
変数ｒのエイリアスのいずれかが効果有り参照されていない場合（ステップＳ５８のＮｏ）、リソース捕捉関数のエラー処理の経路であるとして捕捉失敗候補経路数を１加算する（ステップＳ５９）。
【００９６】
ステップＳ５４〜Ｓ５９の処理で、関数ｆ，ｇと変数ｒの出現パタンの検査が終了すると、捕捉後使用区間調査フラグがｔｒｕｅである場合は、好適経路数を１加算する（ステップＳ６３）。なお、実行経路ｐがリソース捕捉関数のエラー処理の経路であるときも好適経路数は１加算される。つまり、実行経路ｐがリソース捕捉関数のエラー処理の経路であるときは捕捉失敗候補経路数と好適経路数がそれぞれ１加算される。
【００９７】
全ての実行経路ｐ∈ＰについてステップＳ５３〜Ｓ６３を処理すると（ステップＳ６４）、抽出部２２は、全ての実行経路ｐ∈Ｐにおいて関数ｆ，ｇと変数ｒが上記条件（ａ）（ｂ）を満足するときは、関数ｆ，ｇと変数ｒがリソース捕捉関数、リソース解放関数、およびリソース格納変数である可能性はポジティブであると判定する（ステップＳ６５）。具体的には、抽出部２２は、サブ解放漏れ候補経路集合Ｌｃｕｒが含む実行経路ｐ各々について、経路上最後に変数ｒのエイリアスのいずれかが効果有り参照された要素を特定する。そして、抽出部２２は、特定した要素の次の要素から最後の要素までを、実行経路ｐから削除する。抽出部２２は、サブ解放漏れ候補経路集合Ｌｃｕｒが含むすべての実行経路ｐについて同様に処理を実行する。結果として得られた集合をＬｃｕｒ’とする。抽出部２２は、集合Ｌｃｕｒ’が含むユニークな経路の数を算出する。つまり、抽出部２２は、前述した単一化後解放漏れ候補経路数を算出する。そして、抽出部２２は、単一化後解放漏れ候補経路数／（好適経路数＋単一化後解放漏れ候補経路数）の値ｙが、所定の割合ｅ以下か否かを判定する。実行経路集合Ｐが含む実行経路数｜Ｐ｜が好適経路数と一致し、かつ、ｙが所定の割合ｅ以下と判定した場合、抽出部２２は、好適パタン数を１加算する。さらに、抽出部２２は、解放漏れ候補経路集合Ｌにサブ解放漏れ候補経路集合Ｌｃｕｒに含まれる実行経路を追加する（Ｌ＝Ｌ∪Ｌｃｕｒ）。
【００９８】
なお、所定の割合ｅの値は、予め定めておく。ｅは、０から１．０の間の値であり、たとえば、０．５である。所定の割合ｅの値は、実際に本実施形態のプログラム解析方法による実験を行って得られる結果の精度に基づいて決定すればよい。
【００９９】
以上の図１５、１６の処理により、リソース捕捉関数とリソース解放関数である可能性が高い関数ペアを抽出することができる。例えば、図４のソースコードからは、関数ペア（ｍｅｍｐｏｏｌ＿ａｌｌｏｃ，ｍｅｍｐｏｏｌ＿ｆｒｅｅ）が得られる。
【０１００】
（本実施の形態の効果）
上記のように、本実施の形態に係るプログラム解析装置は、解析部と、抽出部とを備える。解析部は、ソースコードを解析して、ソースコードに含まれる関数の一覧を作成する。抽出部は、関数の一覧に含まれる関数のうち２つの関数を、第１の関数および第２の関数とする。そして抽出部は、（ａ）ソースコード中、第１の関数が呼び出された後の経路各々が、（１）第１の関数の返却値を引数として第２の関数が呼び出されている、（２）第１の関数の返却値が使用されていない、（３）第１の関数の返却値が使用されているが、第１の関数の返却値を引数として第２の関数が呼び出されていない、という３つの条件のうちいずれか１つを満足し、かつ、（ｂ）条件（３）を満足する経路の数が、条件（１）、（２）、（３）それぞれを満足する経路の数の合計に占める割合が所定の割合以下である場合に、第１の関数および第２の関数のペアを、リソース捕捉関数およびリソース解放関数のペアとして抽出する。このように、本実施の形態に係るプログラム解析装置は、リソース解放漏れの誤りがある可能性を加味して、ソースコードを解析する。このため、プログラム解析装置は、リソース解放漏れの誤りを含むソースコードからであっても、リソース捕捉関数とリソース解放関数のペアを検出することができる。このため、プログラム解析装置は、プログラム作成者が独自に定義したリソース捕捉関数とリソース解放関数のペアであっても自動的に検出することができる。
【０１０１】
また、本実施の形態において、プログラム解析装置は、条件（ａ）および（ｂ）が満足される場合に、条件（３）を満足する経路を、リソース解放漏れの誤りを含む可能性がある経路として検出する検出部をさらに備える。このため、ソースコード上の誤りを含む可能性がある箇所を、自動的に特定することができる。また、本実施の形態に係るプログラム解析装置によれば、プログラム製造後に、試験をおこなわずとも、静的コード解析によりユーザ定義リソース捕捉関数やリソース解放関数の使い方の誤りを検出することができる。また、本実施の形態に係るプログラム解析装置によれば、ユーザ定義リソース捕捉関数およびリソース解放関数を検出して、未初期化リソースを参照する誤りやリソース解放漏れの誤りを検出することができる。このため、本実施の形態に係るプログラム解析装置によれば、プログラムの品質を向上させ、試験時のバグ数を減少することができる。このため、デバグにかかる作業量を減じ、プログラム開発コストを抑制することができる。
【０１０２】
また、本実施の形態において、解析部はさらに、ソースコードの制御フローグラフを作成し、抽出部は、｛条件（３）を満足する経路数／（条件（１）を満足する経路数＋条件（２）を満足する経路数＋条件（３）を満足する経路数）｝を算出するに当たり、制御フローグラフにおいて、第１の関数が呼び出された後の経路のうち条件（３）を満たす複数の経路上で、（ａ）第１の関数の返却値ｒの値が文中で読み取られ、かつ、他の変数ｗに値が代入される結果として、返却値ｒと他の変数ｗとがエイリアスの関係にならない、（ｂ）返却値ｒが関数の引数の中で参照される、（ｃ）返却値ｒが条件判定の条件式の中で参照される、という３つの条件のうちいずれか１つを満足するノードを特定し、当該ノードよりも後のノードを削除し、ノードを削除した後の複数の経路各々が含むノードが同一となった場合は、複数の経路を１つと数えることで、条件（３）を満足する経路数を算出する。このため、リソース解放漏れの誤りを含む可能性がある経路の数を効率的に算出できる。
【０１０３】
（変形例）
上記実施の形態においては、プログラム解析装置１は、リソース捕捉関数とリソース解放関数のペアを抽出し出力するものとした。これに加え、プログラム解析装置１に、静的コード解析ツールの機能を追加して、抽出したリソース捕捉関数とリソース解放関数のペアを登録し、リソースの未初期化参照やリソース解放漏れ等を解析するよう構成してもよい。
【０１０４】
また、上記実施の形態においては、抽出部２２と検出部２３とを別に設けるものとして説明したが、両者の機能を一体としてもよい。また、プログラム解析装置１において、抽出部２２は、抽出したリソース捕捉関数とリソース解放関数のみを関数ペア集合記憶部３６に記憶するように構成して、検出部２３は備えない構成としてもよい。
【０１０５】
（プログラム）
また、上記実施形態において説明したプログラム解析装置１が実行する処理をコンピュータが実行可能な言語で記述したプログラムを作成することもできる。例えば、実施形態に係るプログラム解析装置１が実行する処理をコンピュータが実行可能な言語で記述したプログラム解析プログラムを作成することもできる。この場合、コンピュータがプログラム解析プログラムを実行することにより、上記実施形態と同様の効果を得ることができる。さらに、かかるプログラム解析プログラムをコンピュータ読み取り可能な記録媒体に記録して、この記録媒体に記録されたプログラム解析プログラムをコンピュータに読み込ませて実行することにより上記実施形態と同様の処理を実現してもよい。
【０１０６】
図１７は、プログラム解析プログラムを実行するコンピュータ１０００を示す図である。図１７に例示するように、コンピュータ１０００は、例えば、メモリ１０１０と、ＣＰＵ１０２０と、ハードディスクドライブインタフェース１０３０と、ディスクドライブインタフェース１０４０と、シリアルポートインタフェース１０５０と、ビデオアダプタ１０６０と、ネットワークインタフェース１０７０とを有し、これらの各部はバス１０８０によって接続される。
【０１０７】
メモリ１０１０は、図１７に例示するように、ＲＯＭ（Read  Only  Memory）１０１１及びＲＡＭ１０１２を含む。ＲＯＭ１０１１は、例えば、ＢＩＯＳ（Basic  Input  Output  System）等のブートプログラムを記憶する。ハードディスクドライブインタフェース１０３０は、図１７に例示するように、ハードディスクドライブ１０３１に接続される。ディスクドライブインタフェース１０４０は、図１７に例示するように、ディスクドライブ１０４１に接続される。例えば磁気ディスクや光ディスク等の着脱可能な記憶媒体が、ディスクドライブ１０４１に挿入される。シリアルポートインタフェース１０５０は、図１７に例示するように、例えばマウス１０５１、キーボード１０５２に接続される。ビデオアダプタ１０６０は、図１７に例示するように、例えばディスプレイ１０６１に接続される。
【０１０８】
ここで、図１７に例示するように、ハードディスクドライブ１０３１は、例えば、ＯＳ１０９１、アプリケーションプログラム１０９２、プログラムモジュール１０９３、プログラムデータ１０９４を記憶する。すなわち、上記のプログラム解析プログラムは、コンピュータ１０００によって実行される指令が記述されたプログラムモジュールとして、例えばハードディスクドライブ１０３１に記憶される。
【０１０９】
また、上記実施形態で説明した各種データは、プログラムデータとして、例えばメモリ１０１０やハードディスクドライブ１０３１に記憶される。そして、ＣＰＵ１０２０が、メモリ１０１０やハードディスクドライブ１０３１に記憶されたプログラムモジュール１０９３やプログラムデータ１０９４を必要に応じてＲＡＭ１０１２に読み出し、各種処理手順を実行する。
【０１１０】
なお、プログラム解析プログラムに係るプログラムモジュール１０９３やプログラムデータ１０９４は、ハードディスクドライブ１０３１に記憶される場合に限られず、例えば着脱可能な記憶媒体に記憶され、ディスクドライブ等を介してＣＰＵ１０２０によって読み出されてもよい。あるいは、プログラム解析プログラムに係るプログラムモジュール１０９３やプログラムデータ１０９４は、ネットワーク（ＬＡＮ（Local  Area  Network）、ＷＡＮ（Wide  Area  Network）等）を介して接続された他のコンピュータに記憶され、ネットワークインタフェース１０７０を介してＣＰＵ１０２０によって読み出されてもよい。
【０１１１】
なお、本実施形態において説明した各処理のうち、自動的におこなわれるものとして説明した処理の全部または一部を手動的に行うこともでき、あるいは、手動的におこなわれるものとして説明した処理の全部または一部を公知の方法で自動的におこなうこともできる。この他、上記文書中や図面中で示した処理手順、制御手順、具体的名称、各種のデータやパラメータを含む情報については、特記する場合を除いて任意に変更することができる。
【０１１２】
上記の実施形態やその変形は、本願が開示する技術に含まれると同様に、特許請求の範囲に記載された発明とその均等の範囲に含まれるものである。
【符号の説明】
【０１１３】
１  プログラム解析装置
１０  入力部
２０  制御部
２１  解析部
２２  抽出部
２３  検出部
３０  記憶部
３１  ソースコード記憶部
３２  サブルーチン展開コード記憶部
３３  関数一覧記憶部
３４  制御フローグラフ記憶部
３５  解析結果記憶部
３６  関数ペア集合記憶部
４０  出力部
【図１】
2017037387.tif 000003
【図２】
2017037387.tif 000004
【図３】
2017037387.tif 000005
【図４】
2017037387.tif 000006
【図５】
2017037387.tif 000007
【図６】
2017037387.tif 000008
【図７】
2017037387.tif 000009
【図８Ａ】
2017037387.tif 000010
【図８Ｂ】
2017037387.tif 000011
【図８Ｃ】
2017037387.tif 000012
【図９】
2017037387.tif 000013
【図１０】
2017037387.tif 000014
【図１１】
2017037387.tif 000015
【図１２】
2017037387.tif 000016
【図１３】
2017037387.tif 000017
【図１４】
2017037387.tif 000018
【図１５】
2017037387.tif 000019
【図１６】
2017037387.tif 000020
【図１７】
2017037387.tif 000021