(57)【要約】【課題】対話的なデバッグ環境を提供するとともにコンテキストを限定させた入出力値をユーザに提示する。【解決手段】本発明のデバッグ支援装置は、関数型言語のプログラムを実行して、関数の呼び出し毎に前記関数の入力値および出力値を取得し、取得した入力値および出力値を、前記関数の親関数と前記関数との親子関係を識別する情報と関連づけてログを取得する手段と、前記プログラム内で定義された関数毎に、定義された関数および前記定義された関数内で呼び出される子関数間のデータの流れを記述したデータフローグラフを生成する手段と、ユーザに対し、連鎖的に呼び出されるｎ個の関数の指定を第１のコンテキストとして受け付ける手段と、前記データフローグラフと前記ログとをもとに、前記第１のコンテキストに対応するログを特定する手段と、特定されたログを出力する出力手段と、を備える。【選択図】図４
2010049489.tif 000002
【特許請求の範囲】
【請求項１】
関数型言語で記述されたプログラムを、前記プログラムを記憶するプログラム記憶装置から読み込むプログラム読込手段と、
前記プログラムを実行して前記プログラムに含まれる関数の呼び出し毎に前記関数の入力値および出力値を取得し、取得した入力値および出力値を、前記関数と前記関数を呼び出した親関数との親子関係の識別情報と関連づけるプログラム実行手段と、
互いに関連づけられた、前記入力値および出力値と前記親子関係の識別情報とからなるログを記憶するログ記憶手段と、
前記プログラム内で定義された関数毎に、定義された関数および前記定義された関数内で呼び出される子関数間のデータの流れを記述したデータフローグラフを生成するデータフローグラフ生成手段と、
ユーザから、連鎖的に呼び出されるｎ（ｎは３以上の整数）個の関数を指定した第１のコンテキストを受け付ける指定手段と、
前記第１のコンテキストにおける１番目および２番目で呼ばれる関数の親子関係に対応するログを前記ログ記憶手段において特定する特定手段と、
（Ａ）前記第１のコンテキストにおけるｍ（ｍは１以上ｎ−２以下の整数）＋１番目で呼び出される関数の入力とｍ＋２番目で呼び出される関数の入力とが同一か否かを前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフに基づき判断し、
（Ｂ）同一のとき、ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから、最新の特定されたログであるターゲットログの入力値と同じ入力値をもつログを特定し、
（Ｃ−１）同一でないとき前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフを辿り、前記ｍ＋１番目で呼び出される関数と同じ入力をもつ関数を特定し、
（Ｃ−２）前記ｍ＋１番目で呼ばれる関数と特定した関数との親子関係に対応するログにおいて、前記ターゲットログと同じ入力値に対応する出力値を取得し、
（Ｃ−３）特定した関数の出力が前記ｍ＋２番目で呼ばれる関数の入力に一致するまで、前記データフローグラフを辿って前記特定した関数の出力を入力としてもつ関数を特定し前記ｍ＋１番目で呼ばれる関数と当該特定した関数との親子関係に対応するログにおいて最新の取得した出力値と同じ入力値に対応する出力値を取得する処理を行い、一致したら前記ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから最新の取得した出力値と同じ入力値をもつログを特定する、
ログ処理手段と、
ｍを１からｎ−２まで順次インクリメントして前記ログ処理手段による処理を繰り返し行うことを制御する制御手段と、
前記ｎ−２に対応して前記ログ処理手段により特定された最新のログを出力する出力手段と、
を備えたデバッグ支援装置。
【請求項２】
前記指定手段は、前記ユーザから、連鎖的に呼び出される２個の関数を指定した第２のコンテキストを受け付け、
前記ログ処理手段は、前記指定手段で前記第２のコンテキストを受け付けたとき、前記第２のコンテキストで指定される２個の関数の親子関係に対応するログを前記ログ記憶手段から検出し、
前記出力手段は、検出されたログを出力する
ことを特徴とする請求項１に記載のデバッグ支援装置。
【請求項３】
前記指定手段は、前記ユーザから単一の関数の指定を受け付け、
前記ログ処理手段は、前記指定手段で前記単一の関数の指定を受け付けたとき、前記単一の関数を子関数として識別する前記識別情報を含むログを前記ログ記憶手段から検出し、
前記出力手段は、検出されたログを出力する
ことを特徴とする請求項１に記載のデバッグ支援装置。
【請求項４】
前記プログラムに含まれる関数の呼び出し毎に、前記関数の入力値および出力値を前記親子関係の識別情報と関連づける命令コードを前記プログラムに追加してトレーサプログラムを生成するトレーサ生成手段をさらに備え、
前記プログラム実行手段は、前記トレーサプログラムを実行する
ことを特徴とする請求項１ないし３のいずれか一項に記載のデバッグ支援装置。
【請求項５】
関数型言語で記述されたプログラムを、前記プログラムを記憶するプログラム記憶装置から読み込むプログラム読込ステップと、
前記プログラムを実行して前記プログラムに含まれる関数の呼び出し毎に前記関数の入力値および出力値を取得し、取得した入力値および出力値を、前記関数と前記関数を呼び出した親関数との親子関係の識別情報と関連づけるプログラム実行ステップと、
互いに関連づけられた、前記入力値および出力値と前記親子関係の識別情報とからなるログをログ記憶手段に記憶するログ記憶ステップと、
前記プログラム内で定義された関数毎に、定義された関数および前記定義された関数内で呼び出される子関数間のデータの流れを記述したデータフローグラフを生成するデータフローグラフ生成ステップと、
ユーザから、連鎖的に呼び出されるｎ（ｎは３以上の整数）個の関数を指定した第１のコンテキストを受け付ける指定ステップと、
前記第１のコンテキストにおける１番目および２番目で呼ばれる関数の親子関係に対応するログを前記ログ記憶手段において特定する特定ステップと、
（Ａ）前記第１のコンテキストにおけるｍ（ｍは１以上ｎ−２以下の整数）＋１番目で呼び出される関数の入力とｍ＋２番目で呼び出される関数の入力とが同一か否かを前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフに基づき判断し、
（Ｂ）同一のとき、ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから、最新の特定されたログであるターゲットログの入力値と同じ入力値をもつログを特定し、
（Ｃ−１）同一でないとき前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフを辿り、前記ｍ＋１番目で呼び出される関数と同じ入力をもつ関数を特定し、
（Ｃ−２）前記ｍ＋１番目で呼ばれる関数と特定した関数との親子関係に対応するログにおいて、前記ターゲットログと同じ入力値に対応する出力値を取得し、
（Ｃ−３）特定した関数の出力が前記ｍ＋２番目で呼ばれる関数の入力に一致するまで、前記データフローグラフを辿って前記特定した関数の出力を入力としてもつ関数を特定し前記ｍ＋１番目で呼ばれる関数と当該特定した関数との親子関係に対応するログにおいて最新の取得した出力値と同じ入力値に対応する出力値を取得する処理を行い、一致したら前記ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから最新の取得した出力値と同じ入力値をもつログを特定する、
ログ処理ステップと、
ｍを１からｎ−２まで順次インクリメントして前記ログ処理ステップを繰り返し行うことを制御する制御ステップと、
前記ｎ−２に対応して前記ログ処理ステップに特定された最新のログを出力する出力ステップと、
をコンピュータに実行させるためのデバッグ支援プログラム。
【請求項６】
前記指定ステップは、前記ユーザから、連鎖的に呼び出される２個の関数を指定した第２のコンテキストを受け付け、
前記ログ処理ステップは、前記指定ステップで前記第２のコンテキストを受け付けたとき、前記第２のコンテキストで指定される２個の関数の親子関係に対応するログを前記ログ記憶手段から検出し、
前記出力ステップは、検出されたログを出力する
ことを特徴とする請求項５に記載のデバッグ支援プログラム。
【請求項７】
前記指定ステップは、前記ユーザから単一の関数の指定を受け付け、
前記ログ処理ステップは、前記指定ステップで前記単一の関数の指定を受け付けたとき、前記単一の関数を子関数として識別する前記識別情報を含むログを前記ログ記憶手段から検出し、
前記出力ステップは、検出されたログを出力する
ことを特徴とする請求項５に記載のデバッグ支援プログラム。
【請求項８】
前記プログラムに含まれる関数の呼び出し毎に、前記関数の入力値および出力値を前記親子関係の識別情報と関連づける命令コードを前記プログラムに追加してトレーサプログラムを生成するトレーサ生成ステップをさらに前記コンピュータに実行させ、
前記プログラム実行ステップは、前記トレーサプログラムを実行する
ことを特徴とする請求項５ないし７のいずれか一項に記載のデバッグ支援プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラムのデバッグ作業を支援するデバッグ支援装置およびデバッグ支援プログラムに関し、たとえばプログラミング言語のうち関数型言語で記述されたプログラムのデバッグに関する。
【背景技術】
【０００２】
プログラミング言語は、C言語やJavaTM言語に代表される手続き型言語と、Haskellといった言語に代表される関数型言語に分類できる。
【０００３】
関数型言語には手続き型言語には無い様々な特徴があるが、その中の一つに、一度変数に値が代入されると、その値を二度と変更できない「単一代入」という特徴がある。関数型言語で記述したプログラムは単一代入という特徴により、変数の値が不変であるため、関数に状態が存在しない。そのため、関数型言語で記述したプログラムの関数は、同じ入力を受け取ると必ず同じ出力を返すという特徴がある。
【０００４】
また、LISPやSCHEMEのような非純粋関数型言語でも、プログラム中で変数の再代入を行わなければ、この特徴は成り立つ。
【０００５】
関数型言語のもうひとつの特徴として、複数の関数を組み合わせてプログラムを作成するプログラミングスタイルが挙げられる。そのため、プログラムの不具合を見つけるためのデバッグを行う際は関数単位で動作チェックを行い、動きのおかしな関数を特定して不具合を検出することが多い。
【０００６】
関数型言語のデバッグ方法の一つとして、関数に渡された値（入力値）と関数が返す値（出力値）を取り出し、入力値と出力値の対応関係をチェックして関数の不具合を見つける方法がある。従来は、関数の入力値、出力値の対応関係を見るために、関数型言語の処理系のトレース機能を用いていた。従来のトレース機能は、実行前にトレース対象の関数を指定してからプログラムの実行を開始し、トレース対象の関数が呼ばれたときに、関数の入力値と出力値を表示していた。プログラマは表示された入力値と出力値の対応関係からトレース対象に指定した関数に不具合があるかどうかを判定していた。
【非特許文献１】ANSI CommonLisp（ポールグレアム著、ピアソン・エデュケーション）
【発明の開示】
【発明が解決しようとする課題】
【０００７】
従来の手法では、プログラムを実行する前にトレース対象の関数を指定する必要があった。これでは、トレース対象の関数を変更して、違う関数の入出力値を確認したい場合、関数の再指定と再実行が必要となる。そのため、対話的に関数の入出力値を調べるデバッグ環境を提供しようとしても、関数を変更する度に、再指定と再実行が必要になるため対話的なデバッグ環境の提供ができなかった。
【０００８】
これに加え従来の手法では、トレース対象の関数が呼ばれたときは常に入出力値を表示してしまうという問題があった。関数型言語のプログラムのデバッグを行う際、検査対象の関数が、別のある特定の関数から呼ばれたときだけ挙動がおかしいという場合がある。この場合、入出力値の表示を、別のある特定の関数から呼ばれたときだけに限定（これをコンテキストの限定と呼ぶ）して入出力値の表示が抑制できると、不具合を示す入出力のペアを見つけやすくなりデバッグ効率を上げることができる。
【０００９】
しかし、従来の手法では、トレース対象の関数が、どのようなコンテキストで呼ばれていても常に入出力値を表示してしまうので、コンテキストを限定させた入出力値の表示の抑制ができなかった。
【００１０】
本発明は、対話的なデバッグ環境を提供するとともにコンテキストを限定させた入出力値をユーザに提示できるようにしたデバッグ支援装置およびデバッグ支援プログラムを提供する。
【課題を解決するための手段】
【００１１】
本発明の一態様としてのデバッグ支援装置は、
関数型言語で記述されたプログラムを、前記プログラムを記憶するプログラム記憶装置から読み込むプログラム読込手段と、
前記プログラムを実行して、前記プログラムに含まれる関数の呼び出し毎に前記関数の入力値および出力値を取得し、取得した入力値および出力値を、前記関数と前記関数を呼び出した親関数との親子関係の識別情報と関連づけるプログラム実行手段と、
互いに関連づけられた、前記入力値および出力値と前記親子関係の識別情報とからなるログを記憶するログ記憶手段と、
前記プログラム内で定義された関数毎に、定義された関数および前記定義された関数内で呼び出される子関数間のデータの流れを記述したデータフローグラフを生成するデータフローグラフ生成手段と、
ユーザから、連鎖的に呼び出されるｎ（ｎは３以上の整数）個の関数を指定した第１のコンテキストを受け付ける指定手段と、
前記第１のコンテキストにおける１番目および２番目で呼ばれる関数の親子関係に対応するログを前記ログ記憶手段において特定する特定手段と、
（Ａ）前記第１のコンテキストにおけるｍ（ｍは１以上ｎ−２以下の整数）＋１番目で呼び出される関数の入力とｍ＋２番目で呼び出される関数の入力とが同一か否かを前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフに基づき判断し、
（Ｂ）同一のとき、ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから、最新の特定されたログであるターゲットログの入力値と同じ入力値をもつログを特定し、
（Ｃ−１）同一でないとき前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフを辿り、前記ｍ＋１番目で呼び出される関数と同じ入力をもつ関数を特定し、
（Ｃ−２）前記ｍ＋１番目で呼ばれる関数と特定した関数との親子関係に対応するログにおいて、前記ターゲットログと同じ入力値に対応する出力値を取得し、
（Ｃ−３）特定した関数の出力が前記ｍ＋２番目で呼ばれる関数の入力に一致するまで、前記データフローグラフを辿って前記特定した関数の出力を入力としてもつ関数を特定し前記ｍ＋１番目で呼ばれる関数と当該特定した関数との親子関係に対応するログにおいて最新の取得した出力値と同じ入力値に対応する出力値を取得する処理を行い、一致したら前記ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから最新の取得した出力値と同じ入力値をもつログを特定する、
ログ処理手段と、
ｍを１からｎ−２まで順次インクリメントして前記ログ処理手段による処理を繰り返し行うことを制御する制御手段と、
前記ｎ−２に対応して前記ログ処理手段により特定された最新のログを出力する出力手段と、
を備える。
【００１２】
本発明の一態様としてのデバッグ支援プログラムは、
関数型言語で記述されたプログラムを、前記プログラムを記憶するプログラム記憶装置から読み込むプログラム読込ステップと、
前記プログラムを実行して、前記プログラムに含まれる関数の呼び出し毎に前記関数の入力値および出力値を取得し、取得した入力値および出力値を、前記関数と前記関数を呼び出した親関数との親子関係の識別情報と関連づけるプログラム実行ステップと、
互いに関連づけられた、前記入力値および出力値と前記親子関係の識別情報とからなるログをログ記憶手段に記憶するログ記憶ステップと、
前記プログラム内で定義された関数毎に、定義された関数および前記定義された関数内で呼び出される子関数間のデータの流れを記述したデータフローグラフを生成するデータフローグラフ生成ステップと、
ユーザから、連鎖的に呼び出されるｎ（ｎは３以上の整数）個の関数を指定した第１のコンテキストを受け付ける指定ステップと、
前記第１のコンテキストにおける１番目および２番目で呼ばれる関数の親子関係に対応するログを前記ログ記憶手段において特定する特定ステップと、
（Ａ）前記第１のコンテキストにおけるｍ（ｍは１以上ｎ−２以下の整数）＋１番目で呼び出される関数の入力とｍ＋２番目で呼び出される関数の入力とが同一か否かを前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフに基づき判断し、
（Ｂ）同一のとき、ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから、最新の特定されたログであるターゲットログの入力値と同じ入力値をもつログを特定し、
（Ｃ−１）同一でないとき前記ｍ＋１番目で呼び出される関数に対応するデータフローグラフを辿り、前記ｍ＋１番目で呼び出される関数と同じ入力をもつ関数を特定し、
（Ｃ−２）前記ｍ＋１番目で呼ばれる関数と特定した関数との親子関係に対応するログにおいて、前記ターゲットログと同じ入力値に対応する出力値を取得し、
（Ｃ−３）特定した関数の出力が前記ｍ＋２番目で呼ばれる関数の入力に一致するまで、前記データフローグラフを辿って前記特定した関数の出力を入力としてもつ関数を特定し前記ｍ＋１番目で呼ばれる関数と当該特定した関数との親子関係に対応するログにおいて最新の取得した出力値と同じ入力値に対応する出力値を取得する処理を行い、一致したら前記ｍ＋１番目およびｍ＋２番目で呼ばれる関数の親子関係に対応するログから最新の取得した出力値と同じ入力値をもつログを特定する、
ログ処理ステップと、
ｍを１からｎ−２まで順次インクリメントして前記ログ処理ステップを繰り返し行うことを制御する制御ステップと、
前記ｎ−２に対応して前記ログ処理ステップにより特定された最新のログを出力する出力ステップと、
をコンピュータに実行させることを特徴とする。
【発明の効果】
【００１３】
本発明により、対話的なデバッグ環境を提供するとともにコンテキストを限定させた入出力値をユーザに提示できる。
【発明を実施するための最良の形態】
【００１４】
本発明の実施の形態では、まず関数型言語で記述されたプログラムを実行してすべての関数呼び出しに対して、関数の入力値および出力値を取得し、取得した入力値および出力値を、当該関数と当該関数を呼び出した親関数との親子関係の識別情報と関連づけたログを保存しておく。次いで、ユーザによる関数指定、またはコンテキスト指定（連鎖的に呼び出される２つ以上の関数の指定）を受け付け、ユーザの指定に応じたログを、関数型言語の特徴（関数が同じ入力を得た場合、同じ出力を返すという特徴）を利用して、保存したログから特定して表示する。
【００１５】
なお、以下の記述において、サンプルプログラムをSCHEME言語及びSCHEME言語の１つの処理系であるGaucheで記述しているが、これは説明のためである。このサンプルはSCHEMEで記述しているが、プログラム内で再代入をまったく行っていないため、関数型の特徴を満たしている。
【００１６】
以下、図面を参照しながら、本発明の実施の形態について詳しい説明を行う。
【００１７】
図１は、本発明の実施の形態に従ったデバッグ支援装置の構成を示すブロック図である。
【００１８】
図１のデバッグ支援装置は、トレーサ生成部１１、プログラム実行部１２、ログビューア部１３から成る。
【００１９】
トレーサ生成部１１は、関数型言語で記述されたプログラムをプログラム記憶装置から読み込んでトレーサを生成し、プログラムにトレーサを付加したトレーサ付きプログラムを生成する。トレーサ生成部１１は、関数型言語で記述されたプログラムを、該プログラムを記憶するプログラム記憶装置から読み込むプログラム読込手段を含む。
【００２０】
ここでトレーサとは、関数呼び出しが行われるすべての箇所に対して挿入されるもので、関数に対する入力値と関数からの出力値を取得し、取得した入力値および出力値を、当該関数と当該関数を呼び出した親関数との親子関係の識別情報と関連づけて保存するコードのことである。トレーサのうち、入力値の保存に係わるコードを「入力値保存コード」、出力値の保存に係わるコードを「出力値保存コード」と呼ぶ。
【００２１】
入力値保存コードは、関数への入力値、すなわち、関数呼び出しの際の実引数の値を一時変数に保存し、一時変数の値をログに書き出す。より詳細には、ログの書き出しにおいては、呼び出されている関数の名と、その関数を呼び出している関数（これを親関数と呼ぶ）の関数名とから識別子を求め、その識別子を割り当てたテーブルの入力項目（入力値を格納する項目）に上記入力値（一時変数の値）を追加する。その識別子をもつテーブルがまだ存在しないときは新たに生成する。テーブルは、関数への入力値の個数分の入力項目と、１つの出力項目（出力値を格納する項目）とを有する。
【００２２】
ここでテーブルの識別子の求め方についてその一例を説明する。
【００２３】
テーブルの識別子は、呼び出されている関数の名と、その関数を呼び出している関数（親関数）とを予約語を挟んで結合することで求める。
【００２４】
たとえば、g関数定義の中でadd関数を呼び出している場合、"add in g"という文字列の識別子が求められる。
【００２５】
もし、ある関数定義の中で同じ関数を複数回呼び出している場合は、各呼び出されている関数名にソースコード上での位置や呼び出し順番などを付加することで、識別子の一意性を失わないようにする。たとえば、g関数の中でadd関数を2回呼び出している場合は、プログラム中で先に現れる方を"add1 in g"、後に現れるほうを"add2 in g"とすることで識別子の一意性を保つ。
【００２６】
出力値保存コードは、関数からの出力値、すなわち、関数からの返り値を一時変数に保存し、一時変数の値をログに書き出す。より詳細に、ログへの書き出しにおいては、入力値保存コードと同様にして、テーブルの識別子を求め、その識別子を持つテーブルの出力項目に書き込む。書き出す際は、入力項目が埋まっており、出力項目が空いているところに書き出す。もし、複数の行にわたって出力項目が空いている場合は、最後に入力値が書き込まれた行に対応する出力項目に書き出しを行う（このようなケースは再帰的に関数が呼び出されている場合に起こる）。
【００２７】
ここで入力値保存コードがログを保存するとき、同じ入力値の行が既に存在する場合は、保存を省略しても良い。そうした場合は、ログの量を圧縮することができる。ただし、ログを保存する際に同じ入力値があるかどうかのチェックが入るために、ログ保存時の計算コストが高くなる。これとは別の方法として、プログラムの実行が終了したあと、すべてのログを走査し、同じ入力値を持つ重複する行を削除することでログの量を圧縮しても良い。
【００２８】
図２は、トレーサ生成部１１による処理の手順を示すフローチャートである。
【００２９】
1) プログラムを読み込み、関数呼び出しを行っている箇所を記憶する（S101）。
【００３０】
2) 呼び出されている関数への入力値を取り出すコードと、呼び出されている関数名と親関数名から識別子を生成しその識別子をもつテーブル（ログ）を検索するコードと、取り出した入力値をテーブルに保存するコードとを併せ持った「入力値保存コード」を生成する（S102）。
【００３１】
3) 呼び出されている関数からの出力値を取り出すコードと、呼び出されている関数名と親関数名から識別子を生成しその識別子をもつテーブル（ログ）を検索するコードと、取り出した出力値をテーブルに保存するコードとを併せ持った「出力値保存コード」を生成する（S103）。
【００３２】
4) 入力値保存コードを関数呼び出し直前に実行されるように、また、出力値保存コードを関数呼び出し直後に実行されるように、プログラムに挿入する（S104）。
【００３３】
以上のようにして、関数呼び出しを行っているすべての箇所について入力値保存コードおよび出力値保存コードを生成し挿入することで、トレーサ付きプログラムが生成される。
【００３４】
SCHEME言語で記述されたプログラム内で定義された下記の関数
(define (g x y)
(h (add x y)
(sub x y)))
に対して入力値保存コードおよび出力値保存コードを挿入する例を説明する。
【００３５】
このプログラムでは、入力がx, yであるようなg関数が定義されている。g関数の中では、h関数が呼び出され、h関数への入力は、add関数の返り値“(add x y)”と、sub関数の返り値“(sub x y)”である。さらにadd関数への入力はxとyであり、sub関数への入力はxとyである。以上のことから、g関数は入力としてx,yを受取り、それがadd関数、sub関数の入力になる。そして、add関数、sub関数の出力が、次に、h関数の入力になる。最後に、h関数の出力がg関数の出力になる。
【００３６】
上記の関数への入力値保存コードおよび出力値保存コードの挿入後のコードは、それぞれ内部で呼び出している関数の入力値、出力値を一時変数で保持しておき、それをログに書き込み、最後に、g関数の返り値として、h関数の返り値を返す。以下は挿入後のコードの一例である。なお、このコードはSCHEME言語の処理系の１つであるGaucheでの実行を想定している。
(define (g x y)
(let* ((add-in1 x) ; add関数へ入力を保持
(add-in2 y) ; add関数へ入力を保持
(add-out (add add-in1 add-in2)) ;add関数の出力を保持
(sub-in1 x) ; sub関数の入力を保持
(sub-in2 y) ; sub関数の入力を保持
(sub-out (sub sub-in1 sub-in2)) ; sub関数の出力を保持
(h-in1 add-out) ; h関数の入力を保持
(h-in2 sub-out) ; h関数の入力を保持
(h-out (h h-in1 h-in2))) ; h関数の出力を保持
(log-open "./add_in_g.log") ; add関数のログをオープン
(log-format "add-in1: ~s" add-in1) ; add関数の入力をログに書き込む
(log-format "add-in2: ~s" add-in2) ; add関数の入力をログに書き込む
(log-format "add-out: ~s" add-out) ; add関数の出力をログに書き込む
(log-open "./sub_in_g.log") ; sub関数のログをオープン
(log-format "sub-in1: ~s" sub-in1) ; sub関数の入力をログに書き込む
(log-format "sub-in2: ~s" sub-in2) ; sub関数の入力をログに書き込む
(log-format "sub-out: ~s" sub-out) ; sub関数の出力をログに書き込む
(log-open "./h_in_g.log") ; h関数のログをオープン
(log-format "h-in1: ~s" h-in1) ; h関数の入力をログに書き込む
(log-format "h-in2: ~s" h-in2) ; h関数の入力をログに書き込む
(log-format "h-out: ~s" h-out) ; h関数の出力をログに書き込む
h-out)) ; 最後にh関数を出力をg関数の出力として返す
【００３７】
プログラム実行部１２は、トレーサ生成部１１により生成されたトレーサ付きプログラムを実行して、ログを出力する。より詳細に、プログラム実行部１２は、トレーサ付きプログラムを実行して、関数の呼び出し毎に該関数の入力値および出力値を取得し、取得した入力値および出力値を、該関数の親関数と該関数との親子関係の識別情報と関連づけ、互いに関連づけられた、入力値および出力値と親子関係の識別情報とからなるログを取得する。取得されたログは、ログを記憶するログ記憶手段（図示せず）に記憶される。
【００３８】
次に、ログビューア部１３について説明する。
【００３９】
ログビューア部１３はユーザから対話的な指示を受け取り、ユーザの指示に応じてログ解析を行い、ユーザの所望するログを取り出して表示する。
【００４０】
図３は、ログビューア部１３の詳細構成を示すブロック図である。
【００４１】
ログビューア部１３は、データフローグラフ生成部２１、関数・コンテキスト指定入力部（指定手段）２２、ログ解析部（特定手段、ログ処理手段、制御手段）２３、ログ表示部（出力手段）２４から成る。
【００４２】
データフローグラフ生成部２１は、トレーサ生成部１１に与えられたのと同じプログラムを受け取り、プログラム内で定義された各関数のそれぞれについて、データフローグラフを生成する。データフローグラフとは、関数の出力値が別のどの関数の入力値になるかといった関数間の入出力の関係（すなわち定義された関数および該定義された関数内で呼び出される子関数間のデータの流れ）をグラフにより表現したものである。データグラフの一例を図５に示す。
【００４３】
このデータフローグラフは、SCHEME言語で記述されたプログラム内で定義された下記の関数
(define (g x y)
(h (add x y)
(sub x y)))
についてのデータフローグラフである。この関数についての詳細はすでに述べた通りである説明を省略する。このように関数型言語のプログラムでは、入出力に着目することでひとつの関数定義をひとつのデータフローグラフとして表現できる。
【００４４】
ここでプログラムからデータフローグラフを生成する方法について説明する。
【００４５】
なお、変数が単一代入の場合（一度変数に値が代入されると、その値を二度と変更できない場合）の、データフローグラフの生成手法は、「参考文献：コンパイラの構成と最適化、中田育男著、朝倉出版」に、詳しい説明があるため、ここでは簡単に説明するにとどめる。
（１）最初に関数定義毎にプログラムを分割する。
（２）次に、関数定義から仮引数（上記のg関数の例ではx,y）を取り出し、それを元にデータフローグラフ中の入力値ノードと、一つの出力値ノードを生成する。
（３）次に、関数定義の中で行っている関数呼び出しに対して、呼び出されている関数に対する入力値を示すノード、関数呼び出しを示すノード（上記のg関数の例では“add”、“sub”のノード）、関数からの出力値を示すノード（上記のg関数の例では“出力”のノード）を生成する。
【００４６】
（３）においては、入力値が定義関数の仮引数と等しい場合は、呼び出されている関数に対する入力値ノードを、定義関数に対する入力値ノードに一致させる。また、入力値が別の関数の出力値と等しい場合は、入力値を示すノードを、当該別の関数の関数呼び出しノードに一致させる。呼び出された関数の出力値が定義関数の出力である場合は、呼び出されている関数の出力値を示すノードを、定義関数の出力値ノードに一致させる。
【００４７】
以上の処理（１）〜（３）を定義関数内のすべての関数呼び出しに対して行うことで、データフローグラフが生成できる。
【００４８】
以上のような処理手順を行うことで、プログラム内で定義された各関数についてデータフローグラフを生成する。
【００４９】
関数・コンテキスト指定入力部２２は、ユーザと対話的なやりとりをすることで、ユーザの指示を、受け取る。ユーザの指示は次の3種類に分類できる。
1) 関数指定（すなわち単一の関数の指定）
2) 1階層コンテキスト限定を行った関数指定（すなわち連鎖的に呼び出される２つの関数の連鎖の指定）
3) 2階層以上のコンテキスト限定を行った関数指定（すなわち連鎖的に呼び出される３つ以上の関数の連鎖の指定）
【００５０】
関数・コンテキスト指定入力部２２は、1), 2), 3)のいずれかの指定をユーザができるように、画面にプログラムのソースコードを表示し、指定を促す。
【００５１】
1)の関数指定は、ユーザが関数定義を行っている箇所を指定する方法である（これはたとえば本発明における単一の関数の指定を受け付けることに相当する）。ユーザが関数定義を行っている箇所を指定した場合は、関数・コンテキスト指定入力部２２はユーザが関数指定を指定したものと認識し、関数の指定情報を、ログ解析部２３に入力する（図７（Ａ）参照）。
【００５２】
関数定義を行っている箇所の指定とは、たとえば、SCHEME言語の場合は、関数定義を行っているdefineという文字列や、defineの後ろに並ぶ関数名と引数名のリストを示す文字列や、関数定義全体、すなわち、defineで始まる括弧内全体を選択した場合などである。
【００５３】
2)の1階層のコンテキスト限定は、関数内で関数呼び出しを行っている箇所を指定する方法である（これはたとえば本発明において、連鎖的に呼び出される２個の関数を指定した第２のコンテキストを受け付けることに相当する）。例えば、上記したg関数の中でadd関数を指定したい場合は、g関数内でadd関数呼び出しを行っている箇所を指定すればよい。
【００５４】
g関数内でadd関数を呼び出している箇所の指定とは、たとえば、add関数呼び出しを示すadd文字列を選択した場合などである。こうして得られたコンテキストの限定を表すコンテキスト指定情報をスタックデータとしてログ解析部２３に入力する（図７（Ｂ）参照）。
【００５５】
3)の2階層以上のコンテキスト限定とは、関数呼び出しを行っている箇所を指定し、更にその関数の呼び出しを持つ関数（親関数）を呼び出している更に上の親関数を指定するというように、関数の呼び出しパターンを2階層以上で指定する方法である（これはたとえば本発明において、連鎖的に呼び出されるｎ（ｎは３以上の整数）個の関数を指定した第１のコンテキストを受け付けることに相当する）。
【００５６】
2階層以上のコンテキストを指定するためには、まず、１階層のコンテキスト限定と同じ方法で関数呼び出しを指定する。次に、親関数を呼び出している関数をプログラム全体を検索して検出し、検出した関数を含む一覧を生成し、一覧をユーザに提示する。ユーザはその一覧から一つ関数を指定する。更に上位の親関数の指定（すなわち３階層以上のコンテキストの指定）を行う場合は、同様に呼び出している関数一覧の提示とユーザ選択とを繰り返す。こうして得られたコンテキストの限定をスタックデータとしてコンテキスト指定情報とする（図７（C）参照。図7(C)ではk関数、i関数、g関数経由で、h関数が呼ばれており、kはトップの関数呼び出し、iは２段目の関数呼び出し、gは３段目の関数呼び出し、hは４段目の関数呼び出しに相当する）。
【００５７】
次にログ解析部２３を説明する。
【００５８】
図４は、ログ解析部２３の処理の手順を示すフローチャートである。
【００５９】
1) ログ解析部２３は、関数・コンテキスト指定入力部２２から関数またはコンテキストの指定情報を受け取る（S201）。
【００６０】
受け取った指定情報が、関数指定の場合とコンテキスト指定の場合とで処理内容が異なる。関数指定とコンテキスト指定との識別は、関数・コンテキスト指定情報で指定された関数の個数（スタックデータの段数）からわかる。1段であるときは、関数指定である（図７（A）参照）。2段以上である場合は、コンテキスト指定である（図７（B）および図７（C）参照）。
【００６１】
1-1) 関数の指定情報を受けた場合は、指定された関数のログ（テーブル）をすべて取得する。上述したように、ログ（テーブル）の識別子は、呼び出されている関数の名と親関数名から生成される。したがって、識別子が、呼び出されている関数の名を含んでいるすべてのログ（テーブル）を検索することで、指定された関数に関するすべてのログ（テーブル）を取得できる。
【００６２】
1-2) 各識別子に応じて取得されたログ（テーブル）をすべて結合し、ターゲットログとする（S203）。結合する際に、同じ入力値であるような行は一つにまとめれば、冗長な行が削除されるため、より見やすいログとなる。ただし、この場合、処理の負荷が大きくなる。
【００６３】
1-3) ターゲットログを表示する（S204）。
【００６４】
2-1)コンテキストの指定情報を受けた場合、コンテキスト指定情報のトップ(たとえば図７（Ｃ）のk)と2段目(たとえば図７（Ｃ）のi)の関数呼び出しを取り出し、取り出した関数呼び出しの呼び出し関係に対応するログ（たとえばi in k）を特定する（S205）。最新の特定されたログは「ターゲットログ」と称され、ここではS205で特定されたログが最新であるため、このログがターゲットログに相当する。S205の処理は、たとえば本発明の特定手段の処理に相当する。また、ここでの2段目の関数呼び出し(たとえば図７（Ｃ）のi)を説明の便宜上、「前関数呼び出し」と称する。
【００６５】
2-2) コンテキスト指定情報の中に関数呼び出しが残っているかをチェックする（S206）。残っていない場合は（たとえばコンテキスト指定情報が図７（Ｂ）の１階層コンテキストのときはこれに該当）、ターゲットログを表示する(S204)。残っている場合（たとえばコンテキスト指定情報が図７（Ｃ）の３階層コンテキストのときはこれに該当））は2-3)へ進む。S206の処理は、たとえば本発明の制御手段の処理に相当する。
【００６６】
2-3) コンテキスト指定情報からトップの関数呼び出しを取り出し（たとえば図７（C）のg）、前関数呼び出し（たとえば図７（C）のi）と取り出したトップの関数呼び出しの呼び出し関係に対応するログを取得する（S207）。本ステップS207で取得された最新のログは「フィルタ対象ログ」と称する（S207）。そして、取り出したトップの関数呼び出し（たとえば図７（C）のg）を新たに「前関数呼び出し」と称する（S207）。
【００６７】
2-4) ターゲットログの入力値（たとえばi in kの入力値）を取り出す（S208）。本ステップS208で取り出された入力値および後述するステップS210で取り出された出力値のうち最新の取り出された値はターゲット入力値と称される（S208）。現時点ではS208で取り出された入力値がターゲット入力値に相当する。
【００６８】
2-5) 現在のターゲット入力値が、前関数呼び出し（たとえば図７（C）のg）に対応する関数の入力値かどうかを調べる（S209）。これはたとえばログ処理手段における（Ａ）の処理に相当する。まず、現在のターゲット入力値を表すノードをデータフローグラフから検索する。次に、前関数呼び出しに対応する関数の入力値を表すノードをデータフローグラフから検索する。
【００６９】
これらのノードが同じ値を示している場合は、ターゲット入力値が前関数呼び出しに対応する関数の入力値に一致する。同じ値を示していなければ、ターゲット入力値と、前関数呼び出しに対応する関数の入力値とは異なる。同じ場合は、2-7)へ、違う場合は、2-6)へ進む。
【００７０】
たとえば図６（E）のi関数のデータフローグラフにおいて、現在のターゲット入力値に対応するノードはx,yで、前関数呼び出し（たとえばg）に対応する入力値に対応するノードもx,yであり、したがって、これらのノードが共にx,yで同じである。したがって、この場合、2-7)へ進む。
【００７１】
仮に、図６（C）のg関数のデータフローグラフにおいて、現在のターゲット入力値を表すノードがx,y、前関数呼び出しがhであるとしたときは、hの入力値を表すノードはaddとsubであるため、これらのノードは互いに異なることとなる。したがってこの場合は2-6)へ進むこととなる。
【００７２】
2-6) ターゲット入力値を入力している関数（たとえば図６（C）のadd,sub）の呼び出しのログ（たとえばadd in g, sub in g）を検索する（S210）。検索して得られたログの中で、ターゲット入力値と同じ入力値をもつ行の出力値を取り出す。この取り出した出力値は、新たにターゲット入力値に相当する。この後、2-5)へ進む（S209へ進む）。
【００７３】
2-7) フィルタ対象ログのうち、ターゲット入力値と同じ入力値をもつ行だけを残すようにフィルタリングを行う（S211）。すなわちフィルタ対象ログのうち、ターゲット入力値と同じ入力値をもつ行を含むログを特定する。この特定されたログは新たにターゲットログに相当する。この後、2-2)へ進む（S206へ進む）。
【００７４】
なお、ユーザが指定できる関数・コンテキスト指定情報を関数指定と１階層のコンテキスト指定だけに限定する場合、ログビューア部１３の中のデータフローグラフ生成部２１は無くてもよい。この場合、図４のフローチャートにおいて、ステップS206の「関数呼び出しの指定が残っているか」の選択項目で必ずNOが選択されることとなる。
【００７５】
以上に示した図４の処理において、S207→S208→S209のYES→S211の流れの処理（S209において一度もNOとならないケース）は、たとえば本発明におけるログ処理手段の（Ｂ）の処理に相当する。
【００７６】
また、S207→S208→S209のNO→S210・・・S209のYES→S211の流れの処理（S209において１回以上、NOとなるケース）は、たとえば本発明におけるログ処理手段の（Ｃ−１）〜（Ｃ−３）の処理に相当する。特に、S209のNO→S210の繰り返しは（Ｃ−３）の処理に相当する。
【００７７】
以下、具体例に沿って図１のデバッグ支援装置の各部の動きについて説明する。
【００７８】
下記の[サンプルプログラム]はSCHEME言語で記述したプログラムの一例であるである。以下では、このサンプルプログラムを入力したときに、デバッグ支援装置がどのように動作するかを具体的に説明する。
----------------------------------
[サンプルプログラム]
01: (define (main args)
02:   (k 1 2)
03:   (l 3 4)
04:   (h 5 6)
05:   (j 7 8))
06:
07: (define (add x y)
08:   (+ x y))
09:
10: (define (sub x y)
11:   (- x y))
12:
13: (define (g x y)
14:   (h (add x y)
15:      (sub x y)))
16:
17: (define (h x y)
18:   (* (* x y)
19:      (add x y)))
20:
21: (define (i x y)
22:   (g x y))
23: 
24: (define (j x y)
25:   (g x y))
26: 
27: (define (k x y)
28:   (i (add x 1)
29:      y))
30:
31: (define (l x y)
32:   (i x y))
----------------------------------
【００７９】
[サンプルプログラム]は上から順にmain関数、add関数、sub関数、g関数、h関数、i関数、j関数、k関数、l関数が宣言されており、それぞれの関数内で様々な関数呼び出しが行われている。
【００８０】
トレーサ生成部１１は、[サンプルプログラム]を入力として受け取ってトレーサ（入力値保存コードと出力値保存コード）を生成し、生成したトレーサをプログラムに付与する。
【００８１】
トレーサは、以下の関数呼び出しに対して生成され、関数呼び出しの直前に入力値保存コードを、直後に出力値保存コードが実行されるようにプログラム中に挿入される。
main関数の中では、
k関数呼び出し
l関数呼び出し
h関数呼び出し
j関数呼び出し
に対して作成される。
add関数の中では、
+関数呼び出し
に対して作成される。
sub関数の中では、
-関数呼び出し
に対して作成される。
g関数の中では、
h関数呼び出し
add関数呼び出し
sub関数呼び出し
に対して作成される。
h関数の中では、
一つ目の*関数呼び出し
二つ目の*関数呼び出し
add関数呼び出し
に対して作成される。なお*は乗算を表す。
i関数の中では
g関数呼び出し
に対して作成される。
j関数の中では
g関数呼び出し
に対して作成される。
k関数の中では
i関数呼び出し
add関数呼び出し
に対して作成される。
l関数の中では
i関数呼び出し
に対して作成される。
【００８２】
こうして生成されたトレーサ付きプログラムは、プログラム実行部１２により実行されることで、以下のログが生成される。
【００８３】
[カッコ]内で記述しているのが、ログ（テーブル）の識別子であり、入力項目には、関数に対する入力値が、出力項目には、出力値がそれぞれ書き込まれる。ただし、記述を簡略化するために、組み込み関数の呼び出し、すなわち+関数呼び出し、-関数呼び出し、*関数の呼び出しについてはログの表示を省略している（本来は、組み込み関数呼び出しに対する入出力値も保存される)。
【表１】
2010049489.tif 000003
2010049489.tif 000004
【００８４】
次に、[サンプルプログラム]をログビューア部１３が読み込んだときの動きについて説明する。
【００８５】
データフローグラフ生成部２１は、[サンプルプログラム]を入力して、図６（A）〜図６（H）に示すようなデータフローグラフを生成する。
【００８６】
関数・コンテキスト指定入力部２２は、[サンプルプログラム]を読み込むと、これを表示して、関数またはコンテキストの指定をユーザに促す。以下、（１）関数指定を行う場合、（２）１階層のコンテキスト指定を行う場合、（３）２階層以上のコンテキスト指定を行う場合に分けて、詳細を説明する。
【００８７】
（１）関数指定を行う場合は、関数定義を識別する方法でユーザは指定を行う。
【００８８】
例えば、add関数を指定する場合は、addを定義している7行目のdefineの文字列を選択する。もしくは、addを定義しているdefineをくくっている括弧全体、すなわち、7~8行目を選択する。これを受け関数・コンテキスト指定入力部２２は、図７（A）に示すような、内部に関数名を保持する、関数の指定情報を生成する。
【００８９】
（２）１階層のコンテキスト指定を行う場合は、関数の呼び出し箇所を選択する。
【００９０】
例えば、g関数経由で呼ばれているaddを選択するには、14行目のadd文字列を選択する。これを受け、関数・コンテキスト指定入力部２２は、図７（B）に示すようにg、addとがスタック状に並んだ、１階層のコンテキストの指定情報を生成する。
【００９１】
（３）２階層以上のコンテキスト指定を行う場合は、関数の呼び出し箇所を選択したのちに、その関数の親関数の呼び出しを行っている関数の指定をユーザが行う。
【００９２】
例えば、ユーザがk関数、i関数、g関数経由で呼ばれたh関数のログを見たいとする。その場合は、ユーザは、まず、13行目のg関数内のh関数呼び出しを指定する。次に、ユーザは、更に上位の親関数の呼び出しの指定を行うことを指示する。関数・コンテキスト指定入力部２２は、この指示を受け、g関数呼び出しを内部に持つ関数の一覧を検索する。g関数呼び出しは、22行目、25行目で行われている。したがって、g関数呼び出しを内部に持つ関数は、
i関数
j関数
である。
【００９３】
そのため、関数・コンテキスト指定入力部２２はi関数とj関数を提示し、ユーザに選択を促す。ユーザはここで、i関数を指定し、更に上位の親関数の呼び出しの指定を指示する。これを受け、関数・コンテキスト指定入力部２２は、i関数の呼び出しを行っている関数を検索する。
【００９４】
i関数の呼び出しを行っているのは、28行目、32行目である。したがって、i関数の呼び出しを行っているのは
k関数、
l関数
である。
【００９５】
関数・コンテキスト指定入力部２２は、k関数とl関数とを提示し、ユーザに選択を促す。ユーザは、ここでk関数を指定し、コンテキスト指定の終了を指示する。
【００９６】
以上の処理から、関数・コンテキスト指定入力部２２は、図７（C）に示すようにk、i、g、hがスタック状に並んだ、２階層以上のコンテキストの指定情報を生成する。
【００９７】
次にログ解析部２３の動きの具体例について説明する。
【００９８】
ログ解析部２３はデータフローグラフと、ログと、関数またはコンテキストの指定情報とを読み込んで処理を行う。以下、ログ解析部２３の処理の具体例を、
（１）add関数が指定された場合
（２）g関数経由でのadd関数の呼び出しが指定された場合
（３）k関数、i関数、g関数経由でのh関数の呼び出しが指定された場合
に分けて説明する。
【００９９】
（１）最初に、関数・コンテキスト指定情報がadd関数を指定した場合について説明する。
【０１００】
ログ解析部２３は、add関数を呼び出しているログ（テーブル）をすべて取得する。
【０１０１】
ログには、関数名がわかるような識別子が付加されているため、簡単に取得できる。
【０１０２】
先に示した[ログの例]の中からaddを呼び出しているログは、
- [add in g]
- [add in h]
- [add in k]
の三つである。
【０１０３】
この三つのログを結合して、以下のようなターゲットログを生成して表示する。
【表２】
2010049489.tif 000005
【０１０４】
（２）次に１階層のコンテキストを指定する例として、g関数経由でadd関数が呼び出された場合（コンテキスト指定情報がadd,gのスタックデータの場合）について説明する。
【０１０５】
g関数経由でadd関数が呼び出された場合は、トップの関数呼び出しがg関数で、二段目がadd関数であることから、g関数内のadd関数呼び出しのログである [add in g]ログを取り出し、以下のようなターゲットログを表示して終了する。
【表３】
2010049489.tif 000006
【０１０６】
（３）次に2階層以上のコンテキストを指定する例として、k関数、i関数、g関数経由でh関数が呼び出された場合（コンテキスト指定情報がh,g,i,kのスタックデータの場合）について説明する。
【０１０７】
コンテキスト指定情報のトップと2段目の関数呼び出しからk関数内のi関数呼び出しに対応するログ [i in k]を特定する。この特定されたログはターゲットログに相当し、i関数は前関数呼び出しに相当する。
【表４】
2010049489.tif 000007
【０１０８】
コンテキスト指定情報には、g, h が残っているため、トップのg関数を取り出す。
【０１０９】
前関数呼び出しのi関数とトップのg関数から、i関数内のg関数呼び出しに対応するログ[g in i]を取り出す。このログはフィルタリング対象ログに相当し、g関数は新たに前関数呼び出しに相当する。
【表５】
2010049489.tif 000008
【０１１０】
次に、ターゲットログの入力値を取り出す。これはターゲット入力値に相当する。
【表６】
2010049489.tif 000009
【０１１１】
ターゲット入力値が前関数呼び出し、すなわちg関数の入力になっているかをチェックする。ターゲット入力値はk関数内でのi関数呼び出しの入力値である。i関数のデータフローグラフ（図６（E）参照）から、i関数の入力値はg関数の入力値であることがわかる。そのため、ターゲット入力値が、次の前関数呼び出しの入力値であることがわかる。
【０１１２】
次に、ターゲット入力値でフィルタ対象ログをフィルタリングする。
【０１１３】
フィルタ対象ログのうちターゲット入力値と同じ入力値をもつログを特定した結果は、
【表７】
2010049489.tif 000010
となる。この特定された新たにターゲットログに相当する。
【表８】
2010049489.tif 000011
【０１１４】
次に、コンテキスト指定情報にh関数が残っているため、h関数を取り出し、前関数呼び出しであるg関数と、取り出したh関数から、[h in g]関数呼び出しのログを取り出す。このログは、新たにフィルタリング対象ログに相当し、h関数は新たに前関数呼び出しに相当する。
【表９】
2010049489.tif 000012
【０１１５】
次に、ターゲットログの入力値を取り出す。これは新たにターゲット入力値に相当する。
【表１０】
2010049489.tif 000013
【０１１６】
ターゲット入力値が、前関数呼び出しであるh関数の入力値であるかをチェックする。
【０１１７】
ターゲット入力値は、g関数の入力値であるため、図６（C）に示すg関数のデータフローグラフを参照する。
【０１１８】
g関数のデータフローグラフから、ターゲット入力値であるg関数の入力値は、h関数の入力値でないことがわかる。g関数のデータフローグラフから、h関数の入力値を求めるには、add関数の出力値とsub関数の出力値を求めればよいことがわかる。
【０１１９】
そこで、g関数内のadd関数呼び出しのログ[add in g]を取り出す。
【表１１】
2010049489.tif 000014
【０１２０】
このログとターゲット入力値からadd関数呼び出しの出力値が4であることがわかる。
【０１２１】
同様にして、g関数内のsub関数呼び出しのログ[sub in g]を取り出す。
【表１２】
2010049489.tif 000015
【０１２２】
このログとターゲット入力値から、sub関数呼び出しの出力値が0であることがわかる。これら、4と0は、新たなターゲット入力値に相当する。
【表１３】
2010049489.tif 000016
【０１２３】
求めたターゲット入力値はadd関数呼び出しの出力とsub関数の出力であるため、g関数のデータフローグラフから、前関数呼び出しであるh関数の入力値であることがわかる。
【０１２４】
そのため、ターゲット入力値でフィルタリング対象のログをフィルタリングする。すなわち、フィルタリング対象ログから、ターゲット入力値と同じ入力値を持つ行のみを特定する。
【０１２５】
ターゲット入力値が
【表１４】
2010049489.tif 000017
であり、
フィルタリング対象ログが
【表１５】
2010049489.tif 000018
であることから、フィルタリングした結果は、次のようになる。
【表１６】
2010049489.tif 000019
【０１２６】
そして、これは新たにターゲットログに相当する。
【表１７】
2010049489.tif 000020
【０１２７】
コンテキスト指定情報には、関数呼び出しの指定が残っていないため、このターゲットログを表示して処理は終了する。
【０１２８】
このようにコンテキストを限定することにより、従来では、h関数呼び出しのログ
【表１８】
2010049489.tif 000021
が表示されていたが、本実施の形態では、k関数, i関数、g関数、h関数とコンテキストの限定ができることで、コンテキストを限定したログ
【表１９】
2010049489.tif 000022
を表示できる。これにより、表示量が抑制されるとともに、不具合を含む、入力および出力間の対応関係が見つけやすくなり、結果としてデバッグ効率を上げることができる。
【０１２９】
以上のように、本実施の形態によれば、事前にすべてのログを保存しておくため、トレース関数の再指定とプログラムの再実行が不要になり、対話的なデバッグ環境が提供できる。
【０１３０】
また、実行時の関数の入出力値の表示を行う際に、関数呼び出しのコンテキストを限定した表示が可能になる。そのため、不具合が、あるコンテキストに限定されて生じる場合、不具合を示す入出力のペアを効率的に見つけることが可能になる。
【図面の簡単な説明】
【０１３１】
【図１】本発明の一実施の形態としてのデバッグ支援装置の構成を示すブロック図。
【図２】トレーサ生成部の動作を説明するフローチャート。
【図３】ログビューアの詳細構成を示すブロック図。
【図４】ログ解析部の動作を説明するフローチャート。
【図５】データフローグラフの一例を示す図。
【図６】データフローグラフの一例を示す図。
【図７】関数指定情報およびコンテキスト指定情報の一例を示す図。
【符号の説明】
【０１３２】
１１：トレーサ生成部
１２：プログラム実行部
１３：ログビューア
２１：データフローグラフ生成部
２２：関数・コンテキスト指定入力部（指定手段）
２３：ログ解析部（特定手段、ログ処理手段、制御手段）
２４：ログ表示部（出力手段）
【図１】
2010049489.tif 000023
【図２】
2010049489.tif 000024
【図３】
2010049489.tif 000025
【図４】
2010049489.tif 000026
【図５】
2010049489.tif 000027
【図６】
2010049489.tif 000028
【図７】
2010049489.tif 000029