(57)【特許請求の範囲】
【請求項１】
コンピュータ・システムにおいてプロセッサを使用し、少なくとも１つの関数を含むコンピュータ・プログラムを分析して、前記コンピュータ・システムが前記コンピュータ・プログラム中のプログラミング・エラーを自動的に検出することを可能にするコンピュータ実行方法であって、
前記コンピュータ・プログラムを、前記コンピュータ・プログラム内の演算子およびオペランドに対応するノードを含む構文解析ツリー構造に変換し、かつ前記コンピュータ・プログラムにより定義された全ての関数を取得する段階と、
前記取得された関数内のステートメントの列からなる制御フロー・パスをトラバースする段階であって、
前記関数用の構造メモリ・モデルを生成して記憶手段に保存する段階であって、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持する、構造メモリ・モデルを保存する段階、
前記構文解析ツリー構造内のノードを前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成する段階、
前記構造メモリ・モデルを使用して前記関数内のステートメントをシミュレートする段階、
前記関数内のステートメントのシミュレートが終了した後で、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれのポインタによっても指し示されないチャンクの検出を含む、プログラミング・エラーを検出する段階、および
検出された前記プログラミング・エラーを出力装置に出力する段階
を含み、
前記制御フロー・パスは、条件文または述語の値に基づいて分岐する選択点を含み、分析された制御フロー・パスを記録した選択点の履歴を使用して未処理の選択点が判断される方法。
【請求項２】
前記出力する段階の後で、前記取得する段階で取得されたコンピュータ・プログラムによって規定される全ての前記関数を識別する段階と、
前記識別された関数を、関数呼出し順序に基づいて順序づけて、関数のリストを作成する段階と、
前記コンピュータ・プログラムによって規定される前記関数のリストの前記順序づけに基づいて、前記コンピュータ・プログラムの分析をスケジューリングする段階と
をさらに含む請求項１に記載の方法。
【請求項３】
前記出力する段階の後で、入力装置から構成制御コマンドを受け入れる段階と、
前記構成制御コマンドに基づいて前記コンピュータ・プログラムの分析を修正する段階とをさらに含む請求項１に記載の方法。
【請求項４】
前記入力装置から指定された関数用の第２構成制御コマンドを受け入れる段階と、
前記第２構成制御コマンドに基づいて前記の指定された関数の分析を修正する段階とをさらに含む請求項３に記載の方法。
【請求項５】
前記入力装置から指定されたステートメント用の第３構成制御コマンドを受け入れる段階と、
前記第３構成制御コマンドに基づいて前記の指定されたステートメントの分析を修正する段階と
をさらに含む請求項４に記載の方法。
【請求項６】
制御フロー・パスをトラバースする前記段階が、
前記制御フロー・パス中で前記未処理の選択点を識別する段階と、
前記未処理の選択点を、複数の分岐を含むツリー内のノードで表す段階と、
未選択の分岐を無作為に選択することにより、前記未処理の選択点を解決する段階と
をさらに含む請求項１に記載の方法。
【請求項７】
コンピュータ・システムにおいてプロセッサを使用し、１つまたは複数のステートメントを含むコンピュータ・プログラムを分析して、前記コンピュータ・システムが前記コンピュータ・プログラム中のプログラミング・エラーを自動的に検出することを可能にするコンピュータ実行方法であって、
前記コンピュータ・プログラムを検索して、条件文、述語および前記ステートメントの列を含む制御フロー・パスを取得する段階と、
前記取得された制御フロー・パスをトラバースする段階であって、
前記制御フロー・パス上の構造メモリ・モデルを記憶手段に保存する段階であって、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持する、構造メモリ・モデルを保存する段階、
前記コンピュータ・プログラムの変数名を、前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成する段階、
前記構造メモリ・モデルを使用して前記ステートメントをシミュレートする段階、
前記シミュレートが終了した後で、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれの変数によっても指し示されないチャンクの検出を含むプログラミング・エラーを検出する段階を含み、
前記シミュレートする段階において、前記制御フロー・パス内で分岐する選択点を履歴に記録し、前記トラバースする段階において、前記履歴を使用して未処理の選択点を判断する方法。
【請求項８】
前記コンピュータ・プログラムは構文解析ツリー構造により表現される請求項７に記載の方法。
【請求項９】
制御フロー・パスを前記コンピュータ・プログラムを通してトラバースする前記段階が、
前記制御フロー・パス中で前記未処理の選択点を識別する段階と、
前記未処理の選択点を、複数の分岐を含むツリー中のノードで表す段階と、
未選択の分岐を無作為に選択することにより、前記未処理の選択点を解決する段階と
をさらに含む請求項７に記載の方法。
【請求項１０】
前記未処理の選択点を解決する前記段階が、
前記選択点の履歴を保存する段階と、
第２の未処理の前記分岐を無作為に選択する段階とをさらに含む請求項９に記載の方法。
【請求項１１】
制御フロー・パスを前記コンピュータ・プログラムを通してトラバースする前記段階が、
前記構造メモリ・モデルを更新して、前記未処理の選択点を解決する前記段階を反映する段階をさらに含む請求項９に記載の方法。
【請求項１２】
前記コンピュータ・プログラムを分析して関数呼出しを識別する段階と、
前記関数呼出しに対応する呼び出された関数のデータ構造を見つける段階と、
前記関数呼出しに対応する呼び出された関数の前記データ構造を取り出す段階とをさらに含む請求項７に記載の方法であって、前記構造メモリ・モデルを使用して前記ステートメントをシミュレートする前記段階が、
前記関数呼出しに対応する呼び出された関数の前記データ構造を使用して前記関数呼出しを分析する段階をさらに含む方法。
【請求項１３】
前記構造メモリ・モデル中の前記プログラミング・エラーが、メモリの初期化されていない部分を知らせる請求項７に記載の方法。
【請求項１４】
実行可能コンピュータ・プログラム・コードを記憶するメモリと、前記メモリに機能的に結合されたプロセッサとを含むコンピュータ・システムであって、前記プロセッサは前記コンピュータ・プログラム・コードに含まれたコンピュータ実行可能命令に応答し、前記コンピュータ・プログラム・コードは前記メモリに格納されたコンピュータ・プログラム中のエラーを検出するためのエラー検出プロセッサのコンピュータ・プログラム・コードを含み、前記コンピュータ・プログラムは１つまたは複数のステートメントを含み、前記プロセッサは、前記エラー検出プロセッサのコンピュータ・プログラム・コードを実行する際、自動的に
前記コンピュータ・プログラム用の構造メモリ・モデルを生成して記憶手段に保存し、前記コンピュータ・プログラムは条件文、述語および前記ステートメントの列を含む制御フロー・パスを含み、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持し、
前記コンピュータ・プログラムの変数名を、前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成し、
前記エラー検出プロセッサのコンピュータ・プログラム・コードの少なくとも一部を含む分析エンジンを使用して、前記コンピュータ・プログラムを通じて前記構造メモリ・モデルを使用した前記制御フロー・パスのトラバースを実行し、
前記エラー検出プロセッサのプログラム・コードの少なくとも一部を含むステートメント・ユニットのプログラム・コードを実行して、前記制御フロー・パス内のステートメントをシミュレートし、さらに
前記制御フロー・パス内のステートメントのシミュレートが終了した後で、エラー生成ユニットのプログラム・コードを実行して、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデル内で検出されたプログラミング・エラーを出力装置に出力し、前記プログラミング・エラーは、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれの変数によっても指し示されないチャンクの検出を含み、
前記シミュレートにおいて、前記制御フロー・パス内で分岐する選択点を履歴に記録し、前記トラバースにおいて、前記履歴を使用して未処理の選択点を判断するコンピュータ・システム。
【請求項１５】
前記プロセッサは、前記エラー検出プロセッサのコンピュータ・プログラム・コードの実行中に、
前記エラー検出プロセッサのコンピュータ・プログラム・コードの少なくとも一部を含むオートモデラを使用して、無関係の動作および二重のパスの１つが削除されたデータ構造を生成することを特徴とする請求項１４に記載のコンピュータ・システム。
【発明の詳細な説明】
マイクロフィッシュの付録の相互参照
付録Ａは、本開示の一部であり、合計で２１４６個のフレームを有する２２枚のマイクロフィッシュ・シートからなるマイクロフィッシュの付録である。マイクロフィッシュの付録Ａは、本発明の一実施態様におけるコンピュータ・プログラムおよび関連データのリストである。この実施形態については以下でより完全に説明する。
本特許文書の開示の一部には、著作権保護を受ける内容が含まれる。著作権所有者は、特許商標庁の特許ファイルに記録された本特許文書または本特許開示を正確に複製することには異議を唱えないが、それ以外の場合にはすべての著作権を留保する。
発明の背景
発明の分野
本発明は、コンピュータ・プログラムの分析に関し、詳細には、構造メモリ・モデルに対してコンピュータ・プログラムをシミュレートされた実行の効果を分析することによってコンピュータ・プログラムのプログラミング・エラーを検出することに関する。
背景
コンピュータ・プログラムを開発する際には、完成したコンピュータ・プログラムの正しさを保証することに多大な努力が払われる。コンピュータ・プログラムの目的は、指定された入出力関数をインプリメントすることである。コンピュータ・プログラムの正しさとは、プログラムの仕様、設計、インプリメントにおいてエラーが生じない程度である。コンピュータ・プログラムのエラーを検出する最も一般的な２つの方法は、コンパイル時検査および実行時検査である。
コンパイル時検査とは、形態、構造、または内容に基づいてコンピュータ・プログラムを評価するプロセスである。コンパイル時検査は、プログラムが実行される前に確立できる特性を試験する。「構文検査」は、コンパイル時検査の一形態であり、言語に関して定義された構造規則または文法規則との整合を検証する。たとえば、周知のＣコンピュータ言語で書かれたコンピュータ・プログラムでは、文Ｂ＋Ｃ＝Ａを使用した場合、正しい形式はＡ＝Ｂ＋Ｃであるためにエラーが生じる。構文検査は、Ｒｉｃｈａｒｄ  ＣｏｎｗａｙおよびＤａｖｉｄ  Ｇｒｉｅｓ著「Ａｎ  Ｉｎｔｒｏｄｕｃｔｉｏｎ  ｔｏ  Ｐｒｏｇｒａｍｍｉｎｇ」（Ｗｉｎｔｈｒｏｐ  Ｐｕｂｌｉｓｈｅｒｓ，Ｉｎｃ．、１９７９年）に詳しく記載されている。
「データ・フロー分析」は、他の種類のコンパイル時検査であり、コンピュータ・プログラム内でデータ転送、使用、変換が実行されるシーケンスを分析してプログラミング・エラーを検出する。データ・フロー分析には、制御フロー情報を使用することが含まれる。「制御フロー」は、コンピュータ・プログラムを実行する際に文が実行されるシーケンスである。制御フローは、「制御フロー・パス」、または単に「コード・パス」とも呼ばれる。データ・フロー分析は、代入を行う前に変数を使用することや、、２回連続して変数に代入することや、使用されることのない変数に値を代入することなどのエラーを検出することができる。
コンパイル時検査モジュールの最大の欠点は、このような方法ではコンピュータ・プログラム実行の結果が考慮されないために生じる。コンパイル時検査は、プログラム実行の動的効果を考慮せずに判定できることに限られる。たとえば、カリフォルニア州マウンテンビューのＳｕｎ  Ｍｉｃｒｏｓｙｓｔｅｍｓ社から市販されているＳＰＡＲＣｗｏｒｋｓTM３．０．１．１のプログラミング環境で使用できるｌｉｎｔコンパイル時チェッカは、コンピュータ・コードによる動的制御フローにかかわらずにコンピュータ・コードを分析する。この欠点のために、ｌｉｎｔは、使用中の値を初期設定される前に報告する。したがって、実際には、報告される値は使用中の値とは異なる。
コンパイル時検査によって生成されるエラー・メッセージは通常、内容が不十分であるか、あるいは過剰である。コンピュータ・プログラムの特定の関数は、ある資源が有効である場合、その資源を検査の前に使用することができる。この関数の外部で資源の有効性が検査されない場合、プログラム終了エラーの可能性が報告されないため、データ構造が破壊され、場合によっては貴重なデータが失われる恐れがある。しかし、この関数の前に資源の有効性を検査した場合、エラーが報告されると、この関数の分析が擬エラーで混乱し、大規模なプログラムではコンピュータ・プログラムの分析が無用になる恐れがある。
コンパイル時分析方法で報告される他の種類の擬エラーは、制御フローが進行できない命令の「明らかな」エラーである。文が実行されるシーケンスは多くの場合、特定の変数に関連する特定の値に依存する。コンパイル時検査方法は一般に、特定のコード・パスが実行されるかどうか、あるいはプログラム制御フローがどんな特定の環境の下でコード・パスを流れるかを判定できないので、文は常に実行されるものと仮定する。
実行時検査は、他の主要な種類のプログラミング・エラー検出方法であり、コンピュータ・プログラムを実行中の動作に基づいて評価するプロセスである。実行時検査では、既知の１組の入力を用いてコンピュータ・プログラムを実行し、プログラム結果を予期される結果と比較して検証する。この１組の試験入力、実行条件、予期される結果を「テスト・ケース」と呼ぶ。多くの場合、エラーを見つけるのを助けるために、それぞれの異なる点での選択された変数の値を示すプリントアウト（トレース）が作成される。
概念は簡単であるが、実行時検査の有用性は、コンピュータ・プログラムの複雑さによって制限される。テスト・ケースを構成し、作成し、実行するには多大な労力が必要である。多大な労力を払ったにもかかわらず、実行時検査のエラー検出関数は、選択された特定の１組の入力によって実行されるコード・パスに限られる。ほとんどの最も簡単なコンピュータ・プログラムでは一般に、すべての可能な制御フロー・パスを実行することは実際的ではない。さらに、実行時検査では、コンピュータ・プログラムが完全であり、実行準備が完了している必要がある。関数を分析するにはその関数を実行しなければならないので、関数を、完全なプログラムに組み込むだけでなく試験するには、関数に必要な実行環境を与えるプログラム・シェルを構築する追加の労力が必要である。
典型的なプログラミング・エラー検出方法の欠点を解消する１つの方法が、「Ｃｏｍｐｕｔｅｒ  Ｐｒｏｃｅｓｓ  Ｒｅｓｏｕｒｃｅ  Ｍｏｄｅｌｌｉｎｇ  Ｍｅｔｈｏｄ  ａｎｄ  Ａｐｐａｒａｔｕｓ」と題する米国特許出願第０８／２８９１４８号で本出願人によって提示されている。この出願は、１９９４年８月１０日に出願され、本出願人に譲渡され、引用によって明示的に本明細書と合体されている。このプログラミング・エラー検出方法は、プログラム資源の状態に対するプログラム命令の効果を追跡することによってコンピュータ・プログラムの構成要素を分析する。各資源は、各状態の間のいくつかの状態および遷移によって表される所定の動作を有する。しかし、状態マシンを維持し使用することは面倒であるので、コンピュータ・プロセス資源モデリングの能力はスプリアス・エラーを抑制し、詳細なエラー・メッセージを生成することに限られる。さらに、方法自体の複雑さのために、この方法を具体化する構造を維持し、かつこの方法を新しい種類のプログラミング・エラーおよびプログラミング言語に拡張することは困難である。
実行されるプログラム命令の動作を考慮し、コンピュータ・プログラム内のほぼすべての可能な制御フロー・パスを自動的に考慮し、コンピュータ・プログラムの個々の関数を分析することのできるプログラミング・エラー検出方法が必要である。さらに、呼出し関数を分析する際に被呼関数の動作を考慮するプログラミング・エラー検出方法が必要である。必要とされるプログラミング・エラー検出方法は、維持し、かつ新しいプログラミング言語および異なる種類のエラーに拡張するのも容易でなければならない。必要とされる方法は、スプリアス・エラーを最小限に抑え、詳細なエラー・メッセージを生成することもできるべきである。
発明の概要
本発明によれば、プログラム文の実行をシミュレートすることによってコンピュータ・プログラムの実行時動作を分析するコンピュータ・プログラム・エラー検出システムが提供される。特に、このシステムを使用して、コンピュータ・システム内の関数のサブセットのみ、あるいはプログラム全体を分析することができる。一実施態様では、オブジェクト・ベースの設計方法を使用してシステムの保全性が高められ、同時に高い拡張性が与えられる。
本発明の一実施態様では、コンピュータ・プログラムがプリプロセッサに入力される。プリプロセッサには、構成ファイル、ヘッダ・ファイル、コマンド行情報に含まれる指定された構成オプションも入力される。プリプロセッサは、コンピュータ・プログラムを内部フォーマット構造（構文解析ツリー構造）に変換する。構文解析ツリー構造は、コンピュータ・プログラム内で定義されたすべての関数のリストと共に中間ファイルに変換される。この中間ファイル、構成オプション、コマンド行情報、外部動作モデルは分析エンジンに変換される。
分析エンジン処理ではまず、構成オプションが受け入れられる。構成オプションは、分析エンジンによって実行される分析を制御する。制御構成オプションが決定されると、中間ファイルからコンピュータ・プログラムの内部フォーマット構造が取り込まれる。分析エンジンは、やはり中間ファイルから、コンピュータ・プログラムによって定義されたすべての関数を識別する。コンピュータ・プログラムの内部フォーマット構造が分析され、すべての関数呼出しが識別される。関数分析のスケジューリングは識別された関数呼出しの順序によって制御される。本発明の他の実施態様では、内部フォーマット構造の代わりにコンピュータ・プログラムの異なる表現を使用することができる。たとえば、コンピュータ・プログラムを表すソース・コードを使用することができる。
分析エンジンは、関数を分析する前に、識別された被呼関数に対応するすでに構築されている外部動作モデルを見つけて取り込む。収集された外部動作モデルは、モデル・テーブル・エントリによって表される。各モデル・テーブル・エントリは、モデル・テーブルとして収集される。被呼関数に関する外部動作モデルが見つからない場合、その関数は、欠落しているモデルによって表される。モデル・テーブルは、関数分析中に外部動作モデルを参照することを可能にする。
コンピュータ・プログラムによって定義された各関数の分析はループで実行される。関数分析の開始時には、その関数に対応する内部フォーマット構造がメモリに読み込まれる。分析エンジンは、最大数のパスに到達するか、あるいは分析するパスがもはやなくなるまで、関数を通るコード・フロー・パスを通ることによってこの関数を分析する。パスの最大数は、分析エンジン処理の限界を決定するために構成オプションを用いて設定される。決定的選択点履歴を使用して制御フロー・パスが選択される。いくつかの異なる制御フロー・パスを通る関数のシミュレートされた実行は、ＣＰＨツリーによってモデル化される。制御フロー・パスは未処理の選択点を含むことができる。これは、制御フロー・パス内に処理できない条件文または述語があることを意味する。ＣＰＨツリー内のノードを使用して、未処理の各選択点が表される。未処理の選択点の分解能をシミュレートするように、ノードのエッジがランダムに選択される。ＣＰＨツリー内でパスが選択された後、このパスが分析される。エッジをランダムに選択すると、制御フロー・パス内での文の効果を表す構造メモリ・モデルを更新することによって記憶されるプログラム変数に関する意味が生じる。
選択したすべてのパスが分析された後、分析中の関数の外部動作モデルが収集される。分析中の関数がもはや必要なくなると、この関数の内部フォーマット構造がメモリから解放される。最後に、オートモデラがすべての個々のパス結果を走査し、無関係の動作を削除し、二重の結果を削除する。オートモデラは次いで、残りの結果をパッケージして、分析中の関数の外部動作モデルを生成する。
特定の制御フロー・パスを分析するには、制御フロー・パスに沿って各文をシミュレートする必要がある。分析エンジンは、パス分析の開始時に、分析中の関数に関してのみ指定された構成オプションがあるかどうかを検査する。現在の関数の処理は、検出される構成オプションの影響を受ける。分析エンジンは、分析される各コード・パスごとに、新しい構造メモリ・モデルを構築する。この構造メモリ・モデルを使用して、制御フロー・パスに沿って各文の実行の効果がシミュレートされる。モデル化されたすべてのメモリ位置を追跡する「チャンク・テーブル」と呼ばれるテーブルが設けられる。分析される各コード・パスごとに、コンピュータ・プログラムで使用される変数名をモデル化メモリ内の位置に関連付ける記号テーブルが作成される。
パス内の第１の分を処理する前に、関数の返却値に関するモデル化メモリ位置が作成され、この位置が記号テーブルに挿入される。モデル化メモリ位置は、モデル化中のメモリのアドレス可能な各ユニットあたり１つの記憶値からなる。４バイト・ポインタをモデル化する場合、モデル化メモリ位置は４つの記憶値を含む（１バイトあたり１つの値−最低アドレス可能ユニット）。記憶値は記憶値セットとして収集される。チャンク・テーブルは、すべての記憶値セットを追跡することによってメモリ・モデルを管理する。
メモリ・モデル内に返却値が配置されると、パスに沿って各文が処理される。各文が処理された後、いくつかの異なるコード・パスの間の結果の比較が容易になるように記号テーブルが順序付けされる。パス処理では、リーク検出も実行され、各モデル化メモリ位置が探索され、メモリにおいて、割り付けられているにもかかわらず関数が終了した後にどの記号も指し示さない部分があるかどうかが判定される。検出されたリークについては適切なエラー・メッセージが生成される。パス処理では最後に、メモリ・モデル内のオートモデラ走査構造が、関数の各外部動作モデルに対して実行された試験および各外部動作モデルに加えられた変更を判定する。この情報は、パスに関する結果として要約される。
特定の文の分析では、文がコンピュータ・メモリに与える効果を反映するようにメモリ・モデルを操作する必要がある。分析エンジンは、文処理の開始時に、分析中の文に関してのみ指定された構成オプションがあるかどうかを検査する。現在の文の処理は、検出される構成オプションの影響を受ける。各文は、処理のために適切な文ユニットに分配される。文の各種類ごとに異なる文ユニットがある。一般に、文ユニットは、文中の式を評価し、適切な処理制御結果を再生することによって、プログラム文の実行をシミュレートする。
式のオペランドを表すようにモデル化メモリ位置を作成し、式の演算子をオペランドに適用する効果をシミュレートするようにメモリ・モデルを更新することによって、式が評価される。メモリ・モデルの操作を表す情報が、後でオートモデラによって検査できるようにログされる。演算子を適用する効果のシミュレーションは演算ユニットによって実行される。演算ユニットは、関数を表すのに使用される外部動作モデルと同様な組込みモデルを実行することによって演算をシミュレートする。
文が関数呼出しである場合、被呼関数に対応する外部動作モデルが実行され、この関数呼出しの効果がエミュレートされる。対応する外部動作モデルが存在しない場合、被呼関数が正常にリターンしたという仮定の下にメモリ・モデルが更新される。被呼関数に関してオートモデラによって生成された外部動作モデルを使用して、呼出し関数を分析する際に被呼関数をエミュレートすることができる。
メモリ・モデルで無効な条件が検出された場合、エラー・メッセージが生成される。エラー・メッセージの報告は、構成オプションによって制御される。構成オプションは、ある無効な条件のみを報告することを可能にするか、あるいはある無効な条件の報告を抑制する。さらに、分析エンジンは二重のエラー・メッセージを報告しない。
本発明は、以下の詳細な説明と図面に鑑みてより完全に理解されよう。
【図面の簡単な説明】
第１図は、本発明の一実施形態の入出力のブロック図である。
第２図は、第１図に示した本発明の１つの動作環境のブロック図である。
第３図は、第２図の分析器の内部構造のより詳細なブロック図である。
第４図は、第３図のプリプロセッサのより詳細なブロック図である。
第５図は、Ｃプログラミング言語文の例と対応する構文解析ツリーの図である。
第６図は、第３図の分析エンジンのより詳細なブロック図である。
第７図は、第６図の関数ごと制御ブロックの機能図のブロック図である。
第８図は、第３図の分析エンジンによって実行される処理を表すブロック図である。
第９図は、本発明の一実施形態で使用されるモデル・テーブル・エントリの図である。
第１０図は、第３図の分析エンジンによる処理の開始時に存在する関数呼出し順序付けおよび外部動作関数モデル・インベントリの例の図である。
第１１図は、第８図の分析関数ブロックによって実行される処理を表すブロック図である。
第１２図は、第１１図の分析パス・ブロックによって実行される処理を表すブロック図である。
第１３図は、本発明の一実施形態で使用される記号テーブル・エントリの図である。
第１４ａ図は、記号テーブル内の２つのポインタと、第１２図の順序記号テーブル・ブロックで使用されるモデル化メモリへのそのリンクの高次表現である。
第１４ｂ図は、第１２図の順序記号テーブル・ブロックで使用される記号テーブルに第１４ａ図とは逆の順序で配置された第１４ａ図からの２つのポインタ（およびモデル化メモリへのそのリンク）の高次表現である。
第１５図は、本発明のメモリ作成ユニットの一実施形態によって実行される処理を表すブロック図である。
第１６図は、第１５図のメモリ作成ユニットによって使用される原点コンテキスト構造の図である。
第１７図は、第１５図のメモリ作成ユニットによって使用されるチャンク・データ構造の図である。
第１８図は、第１５図のメモリ作成ユニットによって使用される記憶値ブロックの図である。
第１９図は、第１５図のメモリ作成ユニットによって使用される記憶資源ブロックの図である。
第２０図は、第１５図のメモリ作成ユニットによって作成される各データ構造の間のリンクの高次表現である。
第２１図は、第１１図の初期設定関数ごとデータ構造ブロックによって使用される実行コンテキストブロックの図である。
第２２図は、第１２図のパス・ブロックに沿ってプログラム文で実行される処理を表すブロック図である。
第２３図は、本発明のブロック・ユニットの一実施形態の論理流れ図である。
第２４図は、本発明の式ユニットの一実施形態の論理流れ図である。
第２５ａ図は、第２４図のプロセス演算アクション２４２４で実行される処理の一部を表す論理流れ図である。
第２５ｂ図は、第２４図の演算処理アクション２４２４で実行される処理の、第２５ａ図から始まった説明を完了する論理流れ図である。
第２６図は、第２５ｂ図の演算評価アクション２５３８によって使用される引数情報ブロックの図である。
第２７図は、本発明の演算ユニットの一実施形態の論理流れ図である。
第２８図は、本発明のｉｆ−ｅｌｓｅユニットの一実施形態の論理流れ図である。
第２９図は、本発明のループ実行ユニットの一実施形態の論理流れ図である。
第３０ａ図は、本発明の切換えユニットの一実施形態の一部の論理流れ図である。
第３０ｂ図は、切換えユニットの第３０ａ図から始まった説明を完了する論理流れ図である。
第３１図は、本発明の変数初期設定ユニットの一実施形態の論理流れ図である。
第３２図は、本発明のリターン・ユニットの一実施形態の論理流れ図である。
第３３図は、本発明のＣＰＨ条件選択ユニットの一実施形態の論理流れ図である。
第３４図は、本発明の一実施形態で使用されるメモリ・タイプ情報ブロックの図である。
第３５図は、本発明の一実施形態で使用される取込み値ブロックの図である。
第３６図は、本発明の一実施形態で使用される述語ブロックの図である。
第３７図は、本発明のエラー生成ユニットの一実施形態の論理流れ図である。
好ましい実施形態の詳細な説明
本発明の原則によれば、コンピュータ・プログラムの実行をシミュレートし、プログラミング・エラーを検出する方法および装置が提供される。特に、本発明によれば、新規のエラー検出方法は、コンピュータ・プログラムのソース・コードを仮想マシン上の演算のシーケンスにマップする。仮想イメージ、すなわち、分析中のコンピュータ・プログラムによって使用されるメモリの詳細な構造モデル（「メモリ・モデル」と呼ぶこともある）は、仮想マシンの状態を表す。コンピュータ・プログラム中の各変数は、メモリ・モデル内の固有の位置に関連付けされる。各位置は値を含む。各値は、一意に識別され、変数またはその他のプログラム資源の特定の瞬間を表す。実行可能なプログラム命令は、仮想マシンの命令に変換される。仮想マシンは、メモリ・モデルに含まれる値に命令の動作モデルを適用することによって動作する。モデルを適用すると、不正な演算、無効な値、リーク、その他の種類のエラーが検出される。
コンピュータ・プログラムを分析するには、いくつかの異なるコード・パスを通る複数の反復が必要である。個々のコード・パスを通る間、未処理の選択点が処理される。「選択点」とは、条件または述語の値に基づいて、２組以上のプログラム文のうち１つが、実行されるプログラム文として選択されるコンピュータ・プログラム内の点である。プログラムの変数および資源の部分的な知識のみを用いて分析を行うと、条件値または述語値が求められず、選択点が未処理になる可能性がある。
コード・パスに沿った関数呼出しは、関数の外部動作モデルを実行することによって分析される。この外部動作モデルは、対応する関数が入力されたときに真でなければならないものと、対応する関数が終了するときに真になるものを反映する。コンピュータ・プログラムの複数回の反復によって得られた情報は、分析中のプログラムの外部動作モデルを形成するように抽象化される。
以下の説明では、本発明をより完全に理解していただくために、言語構文、プログラム・インタフェース、サンプル・データなど多数の特定の詳細について述べる。しかし、当業者には、これらの特定の詳細なしに本発明を実施できることが明らかになろう。いくつかの場合には、本発明を不必要にわかりにくくしないように周知のデータ・フォーマットおよびデータ構造については詳しく説明しない。
関数レベルの分析
通常、コンピュータ・プログラムは、すでに開発されている構成要素と新たに書かれたコードを組み合わせることによって開発される。本明細書では、「コード」は、ソース・コード、すなわち、人間が理解できる形式のコンピュータ命令および／またはオブジェクト・コード、すなわち、コンピュータが理解できる形式のコンピュータ命令を指す。コンピュータ・プログラムの構成要素は、１つまたは複数の指定されたタスクを実行するコードの部分である。コンピュータ上でコンピュータ・プログラムを実行するときは、ソース・コードが機械コードに変換され、プログラムがロード・モジュールとしてメモリにロードされる。ロード・モジュールの作成とプログラムの実行についての詳細は、Ａｒｔｈｕｒ  Ｇｉｌｌ著「Ｍａｃｈｉｎｅ  ａｎｄ  Ａｓｓｅｍｂｌｙ  Ｌａｎｇｕａｇｅ  Ｐｒｏｇｒａｍｍｉｎｇ  ｏｆ  ｔｈｅ  ＰＤＰ−１１」（Ｐｒｅｎｔｉｃｅ−Ｈａｌｌ，Ｉｎｃ．、１９７８年）を参照されたい。
コンピュータ・プログラムは任意の数のコンピュータ言語で書くことができる。従来型のコンピュータ言語、すなわち被呼手続き言語では、コンピュータが所与のシーケンス内で実行しなければならない特定の１組の命令をプログラマが記述する。命令とは、プログラミング言語の文であり、コンピュータによって実行される演算と、関連するオペランドのアドレスおよび値を指定する。たとえば、命令Ａ＝Ｂ＋１で、「Ｂ」および「１」はオペランドであり、「＋」は加算演算を指定するために使用される演算子である。一般に、文は実行すべき動作を指定する。手続きコンピュータ言語の例には、Ｃ、Ａｄａ、Ｐａｓｃａｌ、Ｆｏｒｔｒａｎ、ＣＯＢＯＬ、ＰＬ／１がある。
Ｃ＋＋などいくつかの手続き言語はオブジェクト指向である。オブジェクト指向プログラミング言語は、オブジェクト、すなわち関数および関連するデータの概念的なグループ分けを維持する。オブジェクトは、「クラス」と呼ばれる構成要素に構成される。コンピュータ画面上に表示され、コンピュータ・プログラムを作成するためにコンピュータ・プログラマによってリンクされるグラフィカル画像として命令が表現されるため、いくつかのコンピュータ言語はグラフィックス・ベースである。いくつかのコンピュータ言語は、マサチューセッツ州ＣａｍｂｒｉｄｇｅのＬｏｔｕｓ  Ｄｅｖｅｌｏｐｍｅｎｔ  Ｃｏｒｐｏｒａｔｉｏｎから市販されているＬｏｔｕｓ  １−２−３  Ｓｐｒｅａｄｓｈｅｅｔプログラム用のＬｏｔｕｓ  １−２−３マクロ言語など特定のソフトウェア製品に特有の言語である。本発明は、メモリが操作される、任意のコンピュータ言語、すなわち任意のコンピュータ命令プロトコルに適用することができる。
上記ではソース・コード・コンピュータ命令プロトコルについて説明したが、本明細書の教示がオブジェクト・コード形式のコンピュータ命令にも同様に適用できることが理解されよう。本明細書で説明する例示的な実施形態では、分析される特定のコンピュータ言語は周知のＣコンピュータ言語である。
Ｃコンピュータ言語で書かれたコンピュータ・プログラムは通常、いくつかの関数に分割される。関数は、ゼロ個以上のパラメータを入力として受け付け、特定の動作を実行し、多くて１つの戻し項目を出力として生成する。パラメータおよび戻し項目は、メモリに記憶されるデータ構造である。関数は構成要素でも、あるいは構成要素の一部でもよい。本明細書で説明する例示的な実施形態では、コンピュータ・プログラムの各関数が個別に分析される。
コンピュータ・プログラム分析
第１図は、本発明の一実施形態を示す。エラー検出プロセッサ１０２はコンピュータ・プログラム１０４を障害インジケータ１０６およびモデル１１８に変える。障害インジケータ１０６は、コンピュータ・プログラム１０４内の特定のエラーを識別し記述する。本発明の一実施形態では、障害インジケータ１０６はエラー・メッセージの形をとる。エラー・メッセージについては以下で詳しく説明する。モデル１１８は、コンピュータ・プログラム１０４内の対応する関数が実行する入力メモリから出力メモリへのマッピングを定義する。モデル１１８は、対応する関数の外部可視動作の要約表現であるので外部動作モデルである。コンピュータ関数のモデル化については以下で詳しく説明する。
エラー検出プロセッサ１０２によるコンピュータ・プログラム１０４の処理は様々な入力因子の影響を受ける。このような入力因子には、構成ファイル１１０、コマンド行情報１０８、ヘッダ・ファイル１１２、モデル１１８が含まれる。入力因子については以下で詳しく説明する。
第２図は、エラー検出プロセッサ１０２用の１つの典型的な動作環境を示す。第２図の実施形態では、エラー検出プロセッサ１０２は、中央演算処理装置（ＣＰＵ）２０４で実行されるアナライザ２０２を備える。ＣＰＵ２０４は、記憶されているプログラム命令を実行する。アナライザ２０２は、コンピュータ・プログラム１０４、構成ファイル１１０、ヘッダ・ファイル１１２と共にメモリ２０６に含まれる。メモリ２０６はさらに、メイン・メモリ（図示せず）と二次記憶域（図示せず）に細分することができる。メイン・メモリはプログラム命令またはデータを保持し、ＣＰＵ２０４からメイン・メモリに直接アドレスすることができる。二次記憶域は、直接ＣＰＵ２０４の制御を受けることがなく、あるいはＣＰＵ２０４から直接アドレスすることのできないデータを含む。当業者には、メイン・メモリ２０６に含まれている情報をメイン・メモリに記憶するか、あるいは二次記憶域に記憶し、必要に応じてＣＰＵ２０４で実行できるようにメイン・メモリへ転送することができることが認識されよう。
入出力（Ｉ／Ｏ）回路２０８は、データをＣＰＵ２０４へ転送し、ＣＰＵ２０４から受け取る責任を負う。ＣＰＵ２０４、メモリ２０６、入出力回路２０８は、バス２１０と呼ばれる内部データ・チャネルを通して相互接続される。キーボード２１２とマウス２１４は２つの一般的な入力装置であり、ＣＰＵ２０４へのデータおよび命令の入力を助けるように構成される。たとえば、通常、コマンド行情報１０８は、エラー検出プロセッサ１０２に与えるためにキーボード２１２を通して入力される。表示装置２１６とプリンタ２１８は２つの一般的な出力装置であり、ＣＰＵ２０４からのデータの出力を助けるように構成される。第２図の実施形態では、出力信号、すなわち障害インジケータ１０６はメモリに記憶される。当業者には、表示装置２１６やプリンタ２１８など他の出力装置へこの出力信号を送ることもできることが認識されよう。
第３図は、アナライザ２０２の機能図である。プリプロセッサ３０２はコンピュータ・プログラム１０４を対応する構文解析ツリー構造３０４に変換する。プリプロセッサ３０２は構文解析ツリー構造３０４を中間ファイル３０６に格納する。プリプロセッサ３０２は、中間ファイル３０６にも関数分析リスト３１０、すなわち、コンピュータ・プログラム１０４に定義されたすべての関数のリストを格納する。コンピュータ・プログラム１０４に定義されている関数は、分析エンジン３０８によって分析される関数である。分析エンジン３０８は、構文解析ツリー構造３０４を通してエラーを検出し、障害インジケータ１０６を生成する。分析エンジン３０８は、コンピュータ・プログラム１０４の各関数についてのモデル１１８も生成する。モデル１１８および分析エンジン３０８のその他の出力については以下で詳しく説明する。
プリプロセッサ３０２の機能図を第４図に示す。プリプロセッサ３０２は構成ファイル１１０から演算命令を受け取る。構成ファイル１１０は、ユーザがアナライザ２０２をカスタマイズすることを可能にする。構成ファイル１１０に含まれる設定は、コンピュータ・プログラム１０４が分析される環境の特性を決定する。たとえば、本発明の一実施形態では、構成オプション「ｍａｘｉｍｕｍ＿ｐａｔｈｓ」が、各関数について実行される分析の量の限界を設定する。整数オプション値は、アナライザ２０２によって分析されるパスの数の限界を指定する。本発明の一実施形態に関する構成オプションの完全なリストを付録Ｂに示す。
構成ファイル１１０に含まれる構成オプションは構成ファイル・リーダ４０２によって処理される。構成ファイル・リーダ４０２は、構成ファイル１１０から構成オプションを読み込み、構成オプションによって示されたようにパーサ４０４の演算属性を設定する。パーサ４０４は、コンピュータ・プログラム１０４の内部中間表現を作成する。パーサ４０４はヘッダ・ファイル１１２を使用してコンピュータ・プログラム１０４を変換する。一実施形態では、ヘッダ・ファイル１１２は、「＃ｉｎｃｌｕｄｅ」Ｃプリプロセッサ指令を通してＣプログラムによって使用することのできる標準ライブラリ関数を含む。ヘッダ・ファイルは従来技術でよく知られている。ヘッダ・ファイルの詳細な議論については、Ｍａｒｋ  Ｗｉｌｌｉａｍｓ  Ｃｏｍｐａｎｙの「Ａｎｓｉ  Ｃ：Ａ  Ｌｅｘｉｃａｌ  Ｇｕｉｄｅ」（Ｐｒｅｎｔｉｃｅ  Ｈａｌｌ  １９８８年）を参照されたい。
分析の準備として、パーサ４０４はコンピュータ・プログラム１０４を解析する。コンピュータ・プログラムを解析すると、コンピュータ・プログラムがより多くの基本サブユニットに分解され、各サブユニットの間の関係が確立されることによって、プログラムの構文構造が判定される。パーサ４０４は、コンピュータ・プログラム１０４に現われる文が、ソース言語（Ｃ）仕様によって許容されるパターンで生じるかどうかを検査する。バーサ４０４は、言語仕様に違反する文について障害インジケータ１０６を生成する。本発明の一実施形態では、障害インジケータ１０６はエラー・メッセージの形をとる。言語仕様に違反するエラーを「構文エラー」と呼ぶ。
また、他のエラー検出のためにさらに重要なこととして、パーサ４０４は、コンピュータ・プログラム１０４の基本サブユニットを構文解析ツリー構造３０４で表す。構文解析ツリー構造３０４は構文解析ツリーであり、コンピュータ・プログラム１０４の構文構造を示す。ツリーとは、多数の分岐を含む階層構造としてグループ化された要素の集合である。ツリーの一番上の要素をルート・ノードと呼ぶ。末端ノード、すなわち分岐のないノードをリーフ・ノードと呼ぶ。ツリー内の残りのノードは内部ノードである。
構文解析ツリーの概念は、例を介して最もよく理解されよう。第５図は、簡単なＣ文と対応する構文解析ツリーを示す。文５０２「ａ＝ｂ＋１」は２つの式に分解される。一次式は等式であり、「ａ」を二次式によって生成される値と等しく設定する。一次式の２つのオペランドは「ａ」と二次式である。二次式は加算演算であり、「ｂ」に１を加える。二次式の２つのオペランドは「ｂ」と「１」である。文５０２は構文解析ツリー５０４によって表される。構文解析ツリー５０４のルート、すなわちルート・ノード５０６は、等式を表す等式演算子を含む。ルート・ノード５０６の２つの分岐は、等式の２つのオペランドに至る。リーフ・ノード５０８はオペランド「ａ」を含み、内部ノード５１０は、加算演算を表す加算演算子を含む。内部ノード５１０の２つの分岐は加算演算のオペランドに至る。リーフ・ノード５１２は「ｂ」を含み、リーフ・ノード５１４は「１」を含む。
パーサを使用して、コンピュータ・プログラムを解析すること、構文エラー用のエラー・メッセージを生成すること、構文解析ツリーを構築することはすべて、従来技術でよく知られている。コンピュータ・プログラムの解析に関する詳細な議論については、Ａｌｆｒｅｄ  Ｖ．Ａｈｏ、Ｒａｖｉ  Ｓｅｔｈｉ、Ｊｅｆｆｒｅｙ  Ｄ．Ｕｌｌｍａｎ著「Ｃｏｍｐｉｌｅｒｓ：  Ｐｒｉｎｃｉｐｌｅｓ，Ｔｅｃｈｎｉｑｕｅｓ，ａｎｄ  Ｔｏｏｌｓ」（Ａｄｄｉｓｏｎ−Ｗｅｓｌｅｙ  Ｐｕｂｌｉｓｈｉｎｇ  Ｃｏｍｐａｎｙ、１９８６年）を参照されたい。
プリプロセッサ３０２は、構文解析ツリー構造３０４だけでなく、コンピュータ・プログラム１０４に定義されたすべての関数のリストも生成する。このリスト、すなわち関数分析リスト３１０は、構文解析ツリー構造３０４と共に中間ファイル３０６に格納される。分析エンジン３０８は関数分析リスト３１０にアクセスし、どの関数を分析すべきかを判定する。
第６図は、分析エンジン３０８の機能図である。主制御ブロック６０２は分析エンジン３０８の主入口点である。メイン制御ブロック６０２は、ユーザによって直接、あるいは統合スクリプトまたは構築ツールによって間接的に、コマンド行から呼び出される。ユーザは、キーボード２１２またはマウス２１４を通してコマンドを直接入力することによってアナライザ２０２を呼び出す。コマンド行に入力されるキー情報、すなわち、コマンド行情報１０８の一部は（構文解析ツリー構造３０４を含む）中間ファイル３０６のリストであり、分析すべきコンピュータ・プログラムに対応する。コマンド行情報１０８は、構成ファイル１１０の仕様を含むこともできる。主制御ブロック６０２は分析エンジン３０８内の処理の順序を制御する。
初期設定ブロック６０４は分析エンジン３０８内の第１の処理を実行する。初期設定ブロック６０４は、（中間ファイル３０６のリストと構成ファイル１１０の任意選択の仕様とを含む）コマンド行情報１０８とモデル１１８を処理する。処理が完了すると、制御は主制御ブロック６０２に戻る。
次に、処理は関数ごと制御ブロック６０６によって実行される。１つの構文解析ツリー構造３０４は、１つのコンピュータ・プログラムに対応し、一度に分析される。各構文解析ツリー構造３０４は、内部に複数の関数を表すことができる。関数ごと制御ブロック６０６は一度に１つの関数を分析する。関数ごと制御ブロック６０６は構文解析ツリー構造３０４をトラバースし、障害インジケータ１０６を生成する。処理は、分析すべき各構文解析ツリー構造３０４ごとに繰り返される。すべての構文解析ツリー構造３０４が分析された後、制御は主制御ブロック６０２に戻る。
最後の処理は後処理ブロック６０８によって完了される。後処理ブロック６０８は、関数ごと制御ブロック６０６によって分析される関数に対応するモデル１１８を書き出す。モデル１１８は任意の出力媒体に書き出すことができる。通常、モデル１１８は二次記憶域に書き出され、そこで他のコンピュータ・プログラムの分析に使用することができる。後処理ブロック６０８は制御を主制御ブロック６０２に返し、分析が終了する。
分析エンジン３０８によって実行される処理の大部分は、関数ごと制御ブロック６０６内で行われる。関数ごと制御ブロック６０６の機能図を第７図に示す。関数ごと制御ブロック６０６は５つのメイン・オブジェクト上に構築される。オブジェクトとは、機能および関連するデータの概念的なグループである。オブジェクト・ベースの方法を用いて関数ごと制御ブロック６０６を構成することによって、分析エンジン３０８の拡張性が高まり、分析エンジン３０８を保守するのが容易になる。拡張性が高まるのは、他のオブジェクトに影響を及ぼさずに特定のオブジェクト内で機能を追加できるからである。オブジェクトどうしは、慎重に定義されたインタフェースを使用することによって対話する。インタフェースが維持されるかぎり、１つのオブジェクト内の保守が他のオブジェクトに影響を与えることはない。したがって、分析エンジン３０８全体にわたって大規模な補正を施す必要がある場合と比べて、分析エンジン３０８を保守し局所補正を実行するのが容易である。
構文解析ツリー・オブジェクト７０２は、構文解析ツリー構造３０４によって表されたコンピュータ・プログラム１０４内の複数のコード・パスをトラバースする。構文解析ツリー・オブジェクト７０２は、コード・パスを進むにつれて、命令の演算子を対応するオペランドと共に取り込むことによって、コード・パスに沿って命令を処理する。取り込まれた演算子およびオペランドは、シミュレーションのために命令オブジェクト７０６に渡される。構文解析ツリー・オブジェクト７０２は、エミュレーションのために関数呼出しも命令オブジェクト７０６に渡す。命令実行のシミュレーションと関数呼出しのエミュレーションの両方について以下で詳しく説明する。
仮想マシン７０４は、コンピュータ上のコンピュータ・プログラム１０４の実行および内部表現をシミュレートする。仮想マシン７０４は、命令オブジェクト７０６、仮想メモリ・オブジェクト７０８、オートモデル・オブジェクト７１０からなる。命令オブジェクト７０６は、構文解析ツリー・オブジェクト７０２から渡された演算子を解釈する。さらに、命令オブジェクト７０６は、処理中の演算子または関数に対応するモデル１１８を実行する。モデル１１８を実行することの効果は、メモリ・モデルが適切に修正されることである。メモリ・モデルについては以下で詳しく説明する。
仮想イメージ・オブジェクト７０８は仮想イメージ（図示せず）を維持する。仮想イメージとはコンピュータ・メモリの構造モデル（「メモリ・モデル」）である。仮想イメージ・オブジェクト７０８は、メモリ・モデルの位置、コンピュータ・プログラム１０４を「実行」する間に各位置にどんな値が記憶されたか、特定のメモリ・モデル位置でどんな試験が実行されたかを追跡する。仮想イメージ・オブジェクト７０８は、メモリ内の値に作用するｖｉｍプリミティブと呼ばれる１組のプリミティブも維持する。コンピュータ・メモリのモデルとｖｉｍプリミティブについては以下で詳しく説明する。
オートモデル・オブジェクト７１０は、現在分析中の関数のモデル１１８を構築する責任を負う。関数内の各コード・パスが実行された後、オートモデル・オブジェクト７１０は、仮想イメージ・オブジェクト７０８に問合せを行い、関数によって実行された入出力マッピングに関する情報を得る。オートモデル・オブジェクト７１０によって作成されるモデル１１８は、複数のコード・パスを介して仮想イメージ・オブジェクト７０８から得られた情報を抽象化したモデルである。モデル１１８と、それを構築するのに必要な情報については以下で詳しく説明する。
検出される大部分のプログラミング・エラーは仮想イメージ・オブジェクト７０８で見つけられるが、実際の障害インジケータ１０６は障害インジケータ・オブジェクト７１２で生成される。障害インジケータ・オブジェクト７１２は、プログラミング・エラーを識別する情報を受け取る。本発明の一実施形態では、情報がアセンブルされ、障害インジケータ１０６はエラー・メッセージの形でユーザに提示される。エラー・メッセージ処理については以下で詳しく説明する。
アナライザの構成
本発明の一実施形態では、アナライザ２０２のいくつかの異なる構成要素を表すソース・コードは、パッケージと呼ばれるグループにインプリメントされる。パッケージとは、より大きなコンピュータ・プログラムの論理的に関係するサブセットであり、コンピュータ・プログラムに対して関連する１組のサービスを行う。本発明の一実施形態について、表１に、アナライザ２０２を形成するすべてのパッケージをリストする。
0004633203.tif 000002
表１の「使用されるパッケージ」のシーケンスは、「パッケージ」のシーケンスにリストされたパッケージからアクセスされる他のパッケージを示す。パッケージは、それがアクセスする他のすべてのパッケージに依存する。したがって、「使用されるパッケージ」のシーケンスは、パッケージ依存性のリストを示す。依存性に留意するのは、パッケージが、依存する他のパッケージの誤動作の悪影響を受ける可能性があるからである。
ｂｏｔ：ユーティリティ・パッケージ
ｂｏｔ、すなわちユーティリティ・パッケージは、文字列、ファイル、ファイル名、メモリ、集合を操作する汎用関数を与える。これらのユーティリティは、他のパッケージが移植性の問題の影響を受けるのを妨げる。第２図の実施形態では、ＣＰＵ２０４上でアナライザ２０２が実行される。異なるＣＰＵを使用した場合、動作環境から与えられる資源が変更されることがある。ｂｏｔパッケージは、他のすべてのパッケージをこのような変更から保護する。さらに、ｂｏｔパッケージ内のユーティリティは、システム資源を使用する必要のあるパッケージに関する一様な呼出し規約を提供する。頻繁に使用される関数に関する一様な呼出し規約を有する場合、アナライザ２０２の保全性が高まる。ｂｏｔパッケージは他のパッケージには依存しない。
表２は、本発明の一実施形態に含まれるｂｏｔパッケージから与えられるユーティリティを参照したものである。
0004633203.tif 000003
集合
ｂｏｔ＿ｃｏｌユーティリティは集合をサポートする。集合とは、概念的には、順序付けされた１組のメンバまたはこれらのメンバの順序付けされたバッグである（すなわち、複製を許可する）。メンバはキーとして使用することができ、その場合、各メンバに何らかの追加のデータを関連付けることができる。
集合は、種類、内容の説明、サイズを有する。種類は、解釈されない整数に過ぎず、予期される種類を実際の種類と比較するために使用される。したがって、集合は明示的に入力され、すなわち、各集合は特定のデータ・クラスを予期する。内容の説明は、集合が何で構成されているか、たとえば、ビット、整数、コピーされた文字列などを指定する。集合のサイズは、集合中のメンバの数である。
本発明の一実施形態では、以下の項目の集合がサポートされる。
・ブール演算
・指し示された文字列（集合が単に、文字列を指し示すポインタを記憶する場合）
・コピーされた文字列（集合が、文字列にメモリを割り付け、この文字列をコピーする場合）
・整数
・ポインタ（集合が、指し示されているものに関する情報を有さない場合）
・バイト（集合が、これらのバイトの構造に関する情報を有さない場合）
アナライザ２０２での集合の一般的な使用は以下の通りである。
・固定サイズ・ビット・アレイ（抑制コード、選択点履歴）
・名前による参照が重要な可変サイズ文字列リスト（構成オプション）
・記号テーブル：可変サイズであり、解釈されないポインタを指数として有する。
・チャンクおよび取込み値の固定サイズの記憶値
・記憶値のアレイの固定サイズ・サブセット
・（オート・パッケージ内の）パスごと外部テーブル
・述語の集合
・（モデル内の）結果の集合
・（結果内の）外部動作モデルの集合
・モデル・テーブル：可変サイズであり、モデル識別子を指数として有する。
・（ｍｃｉｌによって生成された）関数ポインタの集合
集合は、ｂｏｔ＿ｃｏｌ＿ｃｒｅａｔｅユーティリティを呼び出し初期サイズおよび最大サイズを供給することによって作成される。初期サイズはゼロ要素でよく、最大サイズは無制限でよい。本発明の一実施形態は、集合サイズが無制限であることを示すためにｂｏｔ＿ｃｏｌ＿ｃｒｅａｔｅユーティリティに渡されるＢＯＴ＿ＣＯＬ＿ＮＯ＿ＭＡＸ＿ＳＩＺＥと呼ばれる定数を定義する。固定サイズ集合は、初期サイズを最大サイズ値と等しく設定することによって作成される。固定サイズ集合は、最適化されたいくつかの処理系を可能にする。たとえば、固定サイズ・ブール演算集合はビットとしてインプリメントされる。ｂｏｔ＿ｃｏｌ＿ｃｏｐｙユーティリティを呼び出して既存の集合をコピーするか、あるいはｂｏｔ＿ｃｏｌ＿ｓｕｂｓｅｔユーティリティを呼び出して既存の集合のサブセットを取り出すことによって、集合を作成することもできる。
集合の各メンバはいくつかの関連する生データを有することができる。メンバに関連する生データを有することは、記号テーブルを集合としてインプリメントする場合に有用である。記号テーブルとは名前の値へのマッピングである。集合としてインプリメントされた記号テーブルは、名前をメンバとして表し、その値を関連する生データとして表す。
本発明の一実施形態では、集合はしばしば、アレイをインプリメントするために使用される。新しいメンバの指数を返すｂｏｔ＿ｃｏｌ＿ａｄｄ＿ｍｅｍｂｅｒユーティリティを使用することによって、アレイにメンバが追加される。ｂｏｔ＿ｃｏｌ＿ｇｅｔ＿ｍｅｍｂｅｒユーティリティを呼び出すことによって、特定の指数にあるメンバがアレイから取り込まれる。ｂｏｔ＿ｃｏｌ＿ｇｅｔ＿ｍｅｍｂｅｒ＿ａｎｄ＿ｒａｗユーティリティによってメンバの値とそれに関連する生データの両方を取り込むことができる。ｂｏｔ＿ｃｏｌ＿ｒｅｐｌａｃｅ＿ｍｅｍｂｅｒユーティリティを使用することによってアレイのメンバの値が置き換えられる。
多くの場合、アレイの各メンバを反復する必要がある。アレイの各メンバを通過することは、通常、ｆｏｒループを使用して行われ、当技術分野で十分に理解されている。ｂｏｔ＿ｃｏｌ＿ｇｅｔ＿ｎｕｍ＿ｍｅｍｂｅｒｓユーティリティはアレイのサイズを返し、このユーティリティを使用してｆｏｒループの上限を確立することができる。前述のように、ｆｏｒループの本体内部では、ｂｏｔ＿ｃｏｌ＿ｇｅｔ＿ｍｅｍｂｅｒを使用してアレイの各メンバを取り込むことができる。
本発明の一実施形態では、参照テーブルは通常、集合としてインプリメントされる。ｂｏｔ＿ｃｏｌ＿ｌｏｏｋｕｐ＿ｍｅｍｂｅｒユーティリティを使用して、メンバの指数を特定の値と共に返すことができる。参照テーブルは、入力値と出力値との間の対応を識別する。参照テーブルは従来の技術で十分に理解されている。
分析エンジン３０８の詳細な説明
前述のように、分析エンジン３０８は、障害インジケータ１０６およびモデル１１８を生成するためにユーザによってコマンド行から（あるいは自動化ツールによって間接的に）呼び出される。本発明の一実施形態によれば、分析エンジン３０８の処理はブロック図８００（第８図）で示されている。処理はベース・パッケージアクション８０２（以下では「アクション８０２」と呼ぶ）のグローバル・データ構造初期設定から始まり、この場合、４つのベース・パッケージによって必要とされるグローバル・データ構造が初期設定される。４つのベース・パッケージとはｂｏｔパッケージ、ｅｒｒパッケージ、ｃｔｘパッケージ、ｃｏｎｆパッケージである。アクション８０２は、コンピュータ・プログラム１０４を処理するために分析エンジン３０８によって必要とされるセットアップを実行する。
すべてのパッケージは、ｂｏｔパッケージから与えられるユーティリティを使用する。したがって、ｂｏｔパッケージによって必要とされるグローバル・データ構造がまず初期設定される。初期設定の後で、ｂｏｔパッケージ内のユーティリティを他のパッケージが使用することができる。次に、構成オプションを処理する際に出会うエラーを処理するためにｅｒｒパッケージを使用できるようにｅｒｒパッケージ内のグローバル・データ構造が初期設定される。ｅｒｒパッケージ処理の後で、実行コンテキストブロック２１００、すなわちｃｔｘパッケージによって定義されるグローバル・データ構造が割り付けされクリアされる。ｅｒｒパッケージは、エラー・メッセージに挿入されるコンテキスト情報に関して実行コンテキストブロック２１００を参照する。実行コンテキストブロック２１００については以下で詳しく説明する。実行コンテキストブロック２１００が初期設定された後、ｃｏｎｆパッケージのグローバル・データ構造が初期設定される。第８図の実施形態では、ｂｏｔパッケージ、ｅｒｒパッケージ、ｃｔｘパッケージ、ｃｏｎｆパッケージのグローバル・データ構造の初期設定はルーチンによって実行される。マイクロフィッシュの付録Ａの実施形態では、ｂｏｔパッケージ、ｅｒｒパッケージ、ｃｔｘパッケージ、ｃｏｎｆパッケージのグローバル・データ構造を初期設定するルーチンをそれぞれ、ｂｏｔ＿ｂｅｇｉｎ、ｅｒｒ＿ｂｅｇｉｎ、ｃｔｘ＿ｂｅｇｉｎ、ｃｏｎｆ＿ｂｅｇｉｎと呼ぶ。処理はアクション８０２からデフォルト構成ファイル処理アクション８０４（以下では「アクション８０４」と呼ぶ）へ移る。
構成オプションは、分析エンジン３０８によって実行される多くの処理に影響を与える。したがって、アクション８０２で必要なセットアップが行われると、アクション８０４で構成オプションが処理される。構成オプションは構成ファイル１１０内に記憶される。デフォルト構成ファイル１１０はデフォルト・オプション設定を含む。デフォルト構成ファイル１１０は分析エンジン３０８用の標準構成を生成する。
デフォルト構成ファイル１１０はアクション８０４内で処理される。まず、デフォルト構成ファイルが見つけられる。本発明の一実施形態では、デフォルト構成ファイルはアナライザ２０２のホーム・ディレクトリに格納される。デフォルト構成ファイル１１０が見つかった後、分析エンジン３０８にデジタル・オプション設定がロードされる。デフォルト構成ファイルに含まれるすべてのオプションがロードされるまで、オプション設定が一度に１つずつ読み込まれる。第８図の実施形態では、デフォルト構成ファイル１１０はルーチンによって処理される。マイクロフィッシュの付録Ａの実施形態では、ｃｏｎｆ＿ｌｏａｄ＿ｄｅｆａｕｌｔｓルーチンによってアクション８０４が実行され、このルーチンはｃｏｎｆ＿ｒｅａｄ＿ｆｉｌｅルーチンをすべてのオプションを読み込む。ｃｏｎｆ＿ｒｅａｄ＿ｆｉｌｅルーチンは、構成ファイル１１０全体にわたって１行ずつ反復し、ｃｏｎｆ＿ｐａｒｓｅ＿ｏｐｔｉｏｎルーチンを使用して構成ファイルの各行を解析し、オプションを取り込む。アクション８０４によって実行される関数は当業者によく知られている。
構成オプションは、分析エンジン３０８によって実行される分析のレベルと、分析エンジン３０８によって生成される出力の種類および量を制御する。たとえば、構成オプションは、処理中のコードで実行されるパスの数と、どんなエラーが報告されるかと、エラーが報告される形式と、あるエラーが報告される場所を判定することができる。第８図の実施形態については、構成オプションのリストおよび各オプションの説明はアペンデッィクスＢに含まれている。
処理は、アクション８０４からユーザ指定構成情報処理アクション８０６（以下では「アクション８０６」と呼ぶ）に移り、ユーザ指定構成ファイル１１０が処理される。ユーザは、コマンド行情報１０８内のコマンド行上に構成ファイル１１０を指定することによって分析エンジン３０８内で実行される処理をカスタマイズするオプションを有する。ユーザ指定構成ファイル１１０に設定された構成オプションは、デフォルト構成ファイル１１０に設定された対応するオプションに優先する。
本発明の一実施形態では、コマンド行上の「−ｃｏｎｆｉｇ」制御語を使用してオプションのユーザ指定構成ファイル１１０が識別される。「−ｃｏｎｆｉｇ」制御語の後に空白が続き、その後にユーザ指定構成ファイル１１０の名前が続く。たとえば、「−ｃｏｎｆｉｇ  ｃｕｓｔｏｍ」は、「ｃｕｓｔｏｍ」と呼ばれるユーザ指定構成ファイル１１０を識別する。
アクション８０６はまず、ユーザがオプションの構成ファイル１１０を指定したかどうかを判定する。そうでない場合、アクション８０６ではもはや処理は必要とされない。ユーザ指定構成ファイル１１０が識別された場合、処理はアクション８０４と同様に継続する。アクション８０６内では、ユーザ指定オプション設定が分析エンジン３０８にロードされる。このようなユーザ指定オプション設定は、アクション８０４に設定された対応するデフォルト設定に優先する。ユーザ指定構成ファイル１１０に含まれるすべてのオプションがロードされるまで、オプション設定は一度に１つずつ読み込まれる。第８図の実施形態では、ユーザ指定構成ファイル１１０はルーチンによって処理される。マイクロフィッシュの付録Ａの実施形態では、アクション８０６はｃｏｎｆ＿ｌｏａｄルーチンによって実行され、このルーチンは、ｃｏｎｆ＿ｌｏａｄ＿ｄｅｆａｕｌｔｓルーチンと同様に、ｃｏｎｆ＿ｒｅａｄ＿ｆｉｌｅルーチンを使用してすべてのオプションを読み込む。
アクション８０６は、ユーザによって指定されたコマンド行構成オプションも処理する。コマンド行情報１０８内のコマンド行上に複数の構成オプションを指定することができる。本発明の一実施形態では、制御行構成オプション（およびその値）の前に「−ｐｒｅｆｉｘ＿ｏｐｔ」制御語が指定される。「−ｐｒｅｆｉｘ＿ｏｐｔ」制御語の後で、引用符で囲まれた構成オプションに値が割り当てられる。言い換えれば、コマンド行構成オプション指定は以下の形式を有する。
−ｐｒｅｆｉｘ＿ｏｐｔ“ｏｐｔｉｏｎ  ｎａｍｅ＝ｏｐｔｉｏｎ  ｖａｌｕｅ”
たとえば、「ｍａｘｉｍｕｍ＿ｐａｔｈｓ」構成オプションは、以下のものを指定することによってコマンド行上に設定することができる。
−ｐｒｅｆｉｘ＿ｏｐｔ“ｍａｘｉｍｕｍ＿ｐａｔｈｓ＝３００”
付録Ｂは、本発明の一実施形態についての様々な構成オプションおよび許容されるオプション値を含む。
アクション８０６は、コマンド行構成オプションをコマンド行上のその位置に対して左から右へ処理する。構成オプションがコマンド行上に指定されたか、それとも構成ファイル１１０内に含まれるかにかかわらず、所与のコマンド行構成オプション指定は、すでに指定されているすべての構成オプションに優先する。
処理はアクション８０６から残余グローバル・データ構造初期設定アクション８０８（以下では「アクション８０８」と呼ぶ）へ移り、コンピュータ・プログラム１０４を分析する準備として残りのパッケージが初期設定される。構成オプションをロードした後の、処理を行う方法は知られている。この時点で、処理に必要とされるグローバル・データ構造が初期設定される。本発明の一実施形態では、ａｕｔｏパッケージ、ｃｐｈパッケージ、ｅｘｅパッケージ、ｉｎｓパッケージ、ｍｃｉｌパッケージ、ｓｙｍパッケージ、ｖｉｍパッケージはすべて、グローバル・データ構造を有し、これらの構造を初期設定しなければならない。第８図の実施形態では、ルーチンを使用してパッケージ内のグローバル・データ構造が初期設定される。マイクロフィッシュの付録Ａの実施形態では、「ｐｋｇ＿ｂｅｇｉｎ」と呼ばれるルーチンによってパッケージ内のグローバル・データ構造が初期設定される。「ｐｋｇ」はパッケージの名前を表す。たとえば、ａｕｔｏパッケージ内のグローバル・データ構造は、「ａｕｔｏ＿ｂｅｇｉｎ」と呼ばれるルーチンによって初期設定される。
処理はアクション８０８から中間ファイル読取りアクション８１０（以下では「アクション８１０」と呼ぶ）へ移り、コマンド行情報１０８内のコマンド行上にリストされた中間ファイル３０６が読み取られ、準備処理が実行される。まず、コマンド行に含まれる中間ファイル３０６のリストが取り込まれる。各中間ファイル３０６の内容がメモリに読み込まれる。ユーザは、空白で区切られた複数の中間ファイル３０６をコマンド行上に指定することができる。
プリプロセッサ３０２は、構築されたあらゆる中間ファイル３０６に関数分析リスト３１０を挿入する。関数分析リスト３１０は、対応する中間ファイル３０６内の分析すべきすべての関数を含む（すなわち、構文解析ツリー構造３０４によって表されたプログラムによって定義されたすべての関数のリスト）。分析すべきすべての関数を識別する関数分析マスタ・リストを形成するために、コマンド行上に指定されたすべての中間ファイル３０６から得たすべての関数分析リスト３１０の複合リストが作成される。
分析を必要とするすべての関数の名前が判明した後、処理では続いて、すべての被呼関数の名前が判定される。「被呼関数」は、（通常は一時的に）転送される実行の制御である関数を示す。関数分析マスタ・リストを巡回することによってすべての被呼関数のリストが生成される。分析を必要とする各関数について、対応する構文解析ツリー構造３０４がトラバースされ、呼び出される関数が調べられる。アクション８１０は、すべての被呼関数の名前と関数呼出しの順序の両方を判定する。
分析エンジン３０８は、被呼関数の実行をエミュレートする。分析エンジン３０８は、対応するモデル１１８を実行できる場合、被呼関数のより確実なエミュレーションを実行することができる。そうでない場合、分析エンジン３０８は、通常実行される被呼関数を示すことからなる最低限のエミュレーションを実行する。
すべての被呼関数の名前を収集した後、これらの関数に関して存在するすべてのモデルを収集することが可能である。アクション８１０内で生成される関数呼出しの順序によって、分析エンジン３０８は、プログラム全体がより完全に調べられるように関数分析の順序付けを調整することができる。分析エンジン３０８はできる限り、関数を分析の他の部分でエミュレートすることが必要になる前にその関数を分析しモデル化する。関数分析の適切な順序は、アクション８１０の最後に関数呼出し順序付け情報のトポロジカル・ソートを行うことによって決定される。トポロジカル・ソートによって、順序付けされた関数呼出しのリストが生成される。関数は、順序付けされた関数呼出しのリストに示された順序で処理される。トポロジカル・ソートは当技術分野でよく理解されている。
例１は、第１０図に示されており、関数呼出し順序付けの例を示す。第１０図を参照するとわかるように、関数Ｆ１  １００２は関数Ｆ２  １００４を呼び出す。関数Ｆ２  １００４は関数Ｆ３  １００６およびＦ４  １００８を呼び出す。この例では、関数ｆ１  １００２、ｆ２  １００４、ｆ３  １００６は関数分析マスタ・リスト上にある（すなわち、分析を必要とする）。被呼関数のリストにはｆ２  １００４、ｆ３  １００４、ｆ４  １００８が含まれる。これらの関数のうちで、分析の開始時に存在するのは関数ｆ４  １００８のモデル、ｆ４モデル１０１０だけである。したがって、ｆ４モデル１０１０が実行され、関数ｆ４  １００８の呼出しがエミュレートされる。関数呼出し順序付けでは、分析の開始時にどのモデルが存在するかだけでなく、どの関数を最初に分析するかも決定される。ｆ２  １００４のモデルが構築される前にまずｆ１  １００２を分析すると、ｆ２  １００４の最低限のエミュレーションが行われる。ｆ２  １００４を最初に分析しモデル化した場合は、関数ｆ１  １００２をより詳しく分析することができる。同様な理由で、ｆ２  １００４を分析する前にｆ３  １００６が分析されモデル化される。ｆ３  １００６が分析されモデル化された後、ｆ２  １００４のより完全な分析が可能になり、最終的にｆ１  １００２がより良好に分析される。
処理はアクション８１０からモデル・テーブル構築アクション８１２（以下では「アクション８１２」と呼ぶ）へ移り、モデル・テーブルが構築される。モデル・テーブルとは、モデル・テーブル・エントリ９００を指し示すポインタの集合である。各モデル・テーブル・エントリ９００は、被呼関数リスト上の被呼関数に対応する。モデル・テーブル・エントリ９００を第９図に示す。モデル・テーブル・エントリ９００は、「ｆｕｎｃｔｉｏｎ  ｎａｍｅ（関数名）」９０２、「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ（モデル・ポインタ）」９０４、「ｍｏｄｅｌ  ｓｏｕｒｃｅ（モデル・ソース）」９０６、「ｏｕｔｐｕｔ  ｄｅｓｔｉｎａｔｉｏｎ（出力宛先）」９０８、「ｎｅｗｅｒ  ｍｏｄｅｌ  ｉｎｄｅｘ（新しいモデル・インデックス）」９１０、「ｌｏａｄｅｄ  ｆｌａｇ（ロード済みフラグ）」９１２、「ｍｉｓｓｉｎｇ  ｆｌａｇ（欠落フラグ）」９１４、「ｒｅｐｏｒｔ  ｍｉｓｓｉｎｇ  ｆｌａｇ（欠落報告フラグ）」９１６、「ａｕｔｏｍｏｄｅｌ  ｆｌａｇ（オートモデル・フラグ）」９１８、「ｎｅｗｅｒ  ｍｏｄｅｌ  ｆｌａｇ（新しいモデル・フラグ）」９２０、「ｗｒｉｔｔｅｎ  ｆｌａｇ（書込み済みフラグ）」９２２、「ｒｅｐｌａｃｅ  ｆｌａｇ（置換えフラグ）」９２４、「ｑｕｅｕｅ  ｆｏｒ  ｗｒｉｔｅ  ｆｌａｇ（書込み待ち行列フラグ）」９２６の各フィールドを含む。
フィールド「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」９０２は、モデル・テーブル・エントリ９００に関連付けされた関数の識別子を指定する。フィールド「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４は、モデル・テーブル・エントリ９００によって表されるモデル１１８を指し示す。フィールド「ｍｏｄｅｌ  ｓｏｕｒｃｅ」９０６は、「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４によって指し示されたモデルがどこから読み取られたかを指定する。フィールド「ｏｕｐｕｔ  ｄｅｓｔｉｎａｔｉｏｎ」９０８は、「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４によって指し示されたモデルを書きこむファイルを指し示す。フィールド「ｎｅｗｅｒ  ｍｏｄｅｌ  ｉｎｄｅｘ」９１０は、このモデル・テーブル・エントリ９００が関連付けされているのと同じ関数のモデルのより新しいバージョンを指し示すモデル・テーブル内のエントリのインデックスを指定する。
「ｌｏａｄｅｄ  ｆｌａｇ」９１２は、このテーブル・エントリに関してモデルがロードされているかどうかを示す。「ｍｉｓｓｉｎｇ  ｆｌａｇ」９１４は、このテーブル・エントリに特殊な「ｍｉｓｓｉｎｇ  ｍｏｄｅｌ」が割り当てられているかどうかを示す。「ｒｅｐｏｒｔ  ｍｉｓｓｉｎｇ  ｆｌａｇ」９１６は、このテーブル・エントリに関して「ｍｉｓｓｉｎｇ  ｍｏｄｅｌ」メッセージが発行されているかどうかを示す。「ａｕｔｏｍｏｄｅｌ  ｆｌａｇ」９１８は、「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４によって指し示されたモデルが、現在の分析中にオートモデラによって作成された場合には真である。「ａｕｔｏｍｏｄｅｌ  ｆｌａｇ」９１８は、モデルが最初に、現在のコンテキストのコンテキスト外でオートモデラによって作成された場合でも偽である。「ｎｅｗｅｒ  ｍｏｄｅｌ  ｆｌａｇ」９２０は、このモデル・テーブル・エントリ９００が関連付けされているのと同じ関数の、オートモデラによって生成されたモデル１１８を表すモデル・テーブル・エントリ９００をオートモデラが追加しているかどうかを示す。「ｗｒｉｔｔｅｎ  ｆｌａｇ」９２２は、モデルがファイルに書き出されたかどうかを示す。「ｒｅｐｌａｃｅ  ｆｌａｇ」９２４は、「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４によって指し示されているモデル１１８をオートモデラが置き換えているかどうかを示す。最後に、「ｑｕｅｕｅ  ｆｏｒ  ｗｒｉｔｅ  ｆｌａｇ」は、分析の終了時にモデルに書き出すべきである場合は真である。そうでない場合は偽である。
まず、アクション８１２内で、モデル・テーブルを具体化する集合が作成される。モデル・テーブルはテーブル・エントリ９００をモデル化する１組のポインタであるので、ポインタの集合が作成される。モデル・テーブルの集合が作成されると、テーブル内にエントリはなくなる。次に、モデル・テーブル内の初期エントリが作成される。すなわち、モデル・テーブル・エントリ９００を指し示すメンバがモデル・テーブル集合に追加される。本発明の一実施形態では、モデル・テーブル集合はルーチンによって構築される。マイクロフィッシュの付録Ａの実施形態では、ルーチンｉｎｓ＿ｍｔ＿ｒｅａｄがモデル・テーブルの構築を制御し、ｂｏｔ＿ｃｏｌ＿ｃｒｅａｔｅ＿ｃｏｌｌｅｃｔｉｏｎユーティリティ・ルーチンを呼び出してモデル・テーブル集合を作成する。
アクション８１２は次に、モデル・テーブルによって指し示された初期モデル・テーブル・エントリを作成する。アクション８１２は、アクション８１０内で構築された被呼関数のリスト上の各関数を巡回する。このリスト上の各関数について、モデル・テーブル・エントリ９００が割り付けられ初期設定される。フィールド「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」９０２は現在の被呼関数の名前に設定される。次いで、モデル・テーブル・エントリ９００は、フィールド「ｍｉｓｓｉｎｇ  ｆｌａｇ」９１４を真に設定することによって欠落モデルを示すように設定される。モデル・テーブル集合にメンバを追加することによって、新たに作成されたモデル・テーブル・エントリを指し示すポインタがモデル・テーブルに挿入される。また、オートモデラによって生成されたモデル１１８で欠落モデルを置き換えるべきであることを示すフラグ「ｒｅｐｌａｃｅ  ｆｌａｇ」９２４がオンにされる。このように、処理は被呼関数リスト全体にわたって反復される。したがって、アクション８１２が完了した後、被呼関数リスト上のあらゆる関数に関するモデル・テーブルによって指し示される１つのモデル・テーブル・エントリ９００がある。本発明の一実施形態では、モデル・テーブルはルーチンを通して初期設定される。マイクロフィッシュの付録Ａの実施形態では、ルーチンｍｃｉｌ＿ｇｅｔ＿ｎｅｘｔ＿ｍｏｄｅｌ＿ｔｏ＿ｒｅａｄは被呼関数名のリスト全体にわたって反復され、ルーチンｉｎｓ＿ｍｔ＿ｉｎｓｅｒｔはモデル・テーブル・エントリ９００を作成し、このエントリを欠落モデルを示すように初期設定し、ｂｏｔ＿ｃｏｌ＿ａｄｄ＿ｍｅｍｂｅｒユーティリティ・ルーチンはモデル・テーブル集合にメンバを追加するために使用される。処理はアクション８１２から集合モデル化アクション８１４（以下では「アクション８１４」と呼ぶ）へ移る。
アクション８１４は、モデル・テーブルで参照された各モデル・テーブル・エントリ９００に対応するすでに構築されているモデル１１８（すなわち、被呼関数リスト上のすべての関数のモデル）を収集する。利用可能なモデル１１８を探索する第１のステップは、モデル・ファイルを探索する位置のリストを構築することである。モデル・ファイルとはモデルを含むファイルであり、規約上、ファイル拡張識別子を区別することによってモデル・ファイルが認識される。たとえば、「ｍｏｄ」と「ｍａｒ」は、モデル・ファイルを識別する２つの拡張子である。「ｍｏｄ」拡張子は現在のモデル１１８を含むモデル・ファイルを示し、「ｍａｒ」拡張子は、保存されているモデル１１８を含むモデル・ファイルを示す。単一のモデル・ファイルに複数のモデル１１８を格納することができる。モデル・ファイルは、ファイルにどの関数がモデル化されているかを示すインデックス情報をファイルの開始位置と終了位置に有することができる。
通常、モデル・ファイルはディレクトリに配置され、ファイルを探索する場所のリストは１組のディレクトリである。組内の各ディレクトリは、モデル・ファイルを求めて探索される。適切なファイル拡張子を有するすべてのファイルが処理される。選択された各ファイルについて、モデル・ファイルが割り付けされ開かれる。モデル・ファイルを開いた後、インデックスが走査され、ファイル内のモデル１１８のうちで、分析に必要な関数に対応するモデルがあるかどうかが判定される。これは、モデル・ファイル・インデックス中の関数名を被呼関数リスト上の名前と比較することによって行われる。名前が一致するたびに、一致した関数を表すモデル・テーブル・エントリ９００内で「ｌｏａｄｅｄ  ｆｌａｇ」９１２が真に設定されていないかぎり、対応するモデル１１８が解析されメモリにコピーされる。コピーされたモデル１１８を指し示すポインタは、フィールド「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４にある対応するモデル・テーブル・エントリ９００に入力される。このモデル・テーブル・エントリ９００に関する「ｍｉｓｓｉｎｇ  ｆｌａｇ」はオフにされる。また、この同じモデル・テーブル・エントリ９００について、「ｌｏａｄｅｄ  ｆｌａｇ」９１２が真に設定され、「ｒｅｐｌａｃｅ  ｆｌａｇ」９２４が偽に設定される。「ｌｏａｄｅｄ  ｆｌａｇ」９１２が真に設定されたときは、アクション８１４が、モデル・テーブル・エントリ９００によって表された関数に一致するすべての後続のモデル１１８を無視すべきであることを意味する。すべての一致が処理されると、選択されたモデル・ファイルの処理が完了し、モデル・ファイルが閉じられ割付け解除される。モデル１１８については以下で詳しく説明する。本発明の一実施形態では、アクション８１４はあるルーチンによって実行される。マイクロフィッシュの付録Ａの実施形態では、ルーチンｉｎｓ＿ｍｔ＿ｒｅａｄが、すでに構築されているモデル１１８を見つけ、ルーチンｉｎｓ＿ｍｔ＿ｐａｒｓｅがモデル・ファイル内のモデルを解析する。
アクション８１４は、ファイルのリスト、すなわち出力モデル・ファイル・リストも生成する。このリストは、分析中に構築されたモデル１１８の出力宛先を指定する。出力モデル・ファイル・リストは、モデル１１８がモデル・テーブル・エントリ９００に挿入されるときに動的に構築される。モデル１１８がモデル・テーブル・エントリ９００にリンクされると、出力モデル・ファイル・リストが検査され、モデル１１８によって表される関数のソース中間ファイル３０６と同じファイル名と「ｍｏｄ」のファイル拡張子とを有する対応する出力モデル・ファイルがあるかどうかが調べられる。探している出力モデル・ファイルが見つからない場合、このファイルは出力モデル・ファイル・リストに追加される。ある関数を表すように構築されたモデル１１８は、最初にその関数を定義した中間ファイルに対応する出力モデル・ファイルに格納される。たとえば、中間ファイル「ｔｅｓｔ．ｉｌ」が関数ｆ１を含む場合、関数ｆ１を表すように構築されたモデル１１８は出力モデル・ファイル「ｔｅｓｔ．ｍｏｄ」に格納される。アクション８１４がモデル・テーブル・エントリ９００を初期設定すると、フィールド「ｏｕｔｐｕｔ  ｄｅｓｔｉｎａｔｉｏｎ」９０８が、フィールド「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」９０２で識別された関数を含む中間ファイル３０６に対応する出力モデル・ファイルの名前を記録するように設定される。モデル・ファイルについては以下で詳しく説明する。処理はアクション８１４から関数分析アクション８１６（以下では「アクション８１６」と呼ぶ）へ移る。
アクション８１６は、関数分析マスタ・リスト上のすべての関数を分析する。処理の順序は、順序付き関数呼出しリストによって制御される。関数は、順序付き関数呼出しリスト上の第１の関数から最後の関数まで順次分析される。各関数について、対応する構文解析ツリー構造３０４がメモリに読み込まれる。関数を分析すると、障害インジケータ１０６（エラーが検出された場合）と、分析された関数を表すモデル１１８が生成される。関数の分析が完了すると、メモリに読み込まれた構文解析ツリー構造３０４は破棄される。このように、必要に応じてのみ構文解析ツリー構造３０４を記憶することによって、ＣＰＵ２０４のメモリ資源が節約される。アクション８１６で実行される関数ごと処理については以下で詳しく説明する。処理は、アクション８１６から出力モデルアクション８１８（以下では「アクション８１８」と呼ぶ）へ移る。
アクション８１８は、アクション８１６によって作成されたモデル１１８を記憶する責任を負う。出力モデル・ファイル・リスト内の各出力モデル・ファイルは順次処理される。まず、モデル出力ファイルが作成され、割り付けられ、開かれる。次に、アクション８１８が、モデル・テーブル全体にわたって反復され、各モデル・テーブル・エントリ９００に問合せを行う。フィールド「ｏｕｔｐｕｔ  ｄｅｓｔｉｎａｔｉｏｎ」９０８が現在のモデル出力ファイルの名前に等しく、フラグ「ｑｕｅｕｅ  ｆｏｒ  ｗｒｉｔｅ  ｆｌａｇ」９２６が真である場合、フィールド「ｍｏｄｅｌ  ｐｏｉｎｔｅｒ」９０４によって指し示されたモデル１１８が現在のモデル出力ファイルに格納される。「ｗｒｉｔｔｅｎ  ｆｌａｇ」９２２は真に設定される。
出力モデル・ファイル・リスト内の最後のファイルに対する処理が完了すると、制御はグローバル・データ構造除去アクション８２０（以下では「アクション８２０」と呼ぶ）へ移る。
処理はアクション８２０で終了し、記憶域クリーンナップが行われる。第８図の実施形態では、あるルーチンを使用して、パッケージ内のグローバル・データ構造が除去またはクリーンナップされる。マイクロフィッシュの付録Ａの実施形態では、「ｐｋｇ＿ｅｎｄ」と呼ばれるルーチンを実行することによって、パッケージ内のグローバル・データ構造が除去またはクリーンアップされる。「ｐｋｇ」はパッケージの名前を表す。たとえば、ｅｒｒパッケージ内のグローバル・データ構造は、「ｅｒｒ＿ｅｎｄ」と呼ばれるルーチンによってクリーンナップされる。ｂｏｔ、ｅｒｒ、ｃｏｎｆ、ａｕｔｏ、ｃｐｈ、ｃｔｘ、ｅｘｅ、ｉｎｓ、ｍｃｉｌ、ｓｙｍ、ｖｉｍの各パッケージには「ｐｋｇ＿ｅｎｄ」ルーチンが実行される。この時点で、コンピュータ・プログラム１０４の処理が完了する。
関数分析
前述のように、関数分析マスタ・リスト上にリストされた関数の分析はアクション８１６で行われる。（アクション８１０で実行されるトポロジカル・ソートによって作成される）順序付き関数呼出しリストは、関数が分析される順序を制御する。アクション８１６は、ブロック図１１００（第１１図）に示したように、順序付き関数呼出しリストを巡回し、リスト上の各関数について関数ごと処理を実行する。分析中の関数は現在の関数として指定される。関数ごと処理は、関数ごとデータ構造初期設定アクション１１０２（以下では「アクション１１０２」と呼ぶ）から始まる。
アクション１１０２は、関数ごとに使用されるデータ構造を割り付けるか、あるいは初期設定する。第１１図の実施形態では、あるルーチンを使用することによって、パッケージ内の関数ごとデータ構造を割り付けるか、あるいは初期設定する。マイクロフィッシュの付録Ａの実施形態では、「ｐｋｇ＿ｂｅｇｉｎ＿ｆｕｎｃｔｉｏｎ」（「ｐｋｇ」はパッケージの名前を表す）と呼ばれるルーチンが、パッケージ内の関数ごとデータ構造を割り付けるか、あるいは初期設定する。たとえば、ｅｘｅパッケージ内の関数ごとデータ構造は、「ｅｘｅ＿ｂｅｇｉｎ＿ｆｕｎｃｔｉｏｎ」と呼ばれるルーチンによって割り付けられる。「ｐｋｇ＿ｂｅｇｉｎ＿ｆｕｎｃｔｉｏｎ」ルーチンは、ｃｔｘ、ｍｃｉｌ、ｅｒｒ、ｖｉｍ、ｓｙｍ、ｉｎｓ、ｃｐｈ、ａｕｔｏ、ｅｘｅのパッケージ順序で呼び出される。
アクション１１０２は、実行コンテキストブロック２１００に情報をポストする。実行コンテキストブロック２１００を第２１図に示す。実行コンテキストブロック２１００には、「ｆｉｌｅｎａｍｅ（ファイル名）」２１０２、「ｆｕｎｃｔｉｏｎ  ｎａｍｅ（関数名）」２１０４、「ｃｕｒｒｅｎｔ  ｆｕｎｃｔｉｏｎ（現在の関数）」２１０６、「ｃｕｒｒｅｎｔ  ｉｔｅｒａｔｉｏｎ（現在の反復）」２１０８、「ｃｕｒｒｅｎｔ  ｓｔａｔｅｍｅｎｔ（現在の文）」２１１０、「ｃｕｒｒｅｎｔ  ｌｉｎｅ  ｎｕｍｂｅｒ（現在の行番号）」２１１２、「ｃｕｒｒｅｎｔ  ｅｘｐｒｅｓｓｉｏｎ（現在の式）」２１１４、「ｅｍｕｌａｔｉｏｎ  ｄｅｐｔｈ（エミュレーション深さ）」２１１６、「ｅｍｕｌａｔｉｏｎ  ｃｏｎｔｅｘｔ  ｌｉｓｔ（エミュレーションコンテキストリスト）」２１１８の各フィールドが含まれる。
フィールド「ｆｉｌｅｎａｍｅ」２１０２は、現在の関数を含むソース・ファイルを識別する。フィールド「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」２１０４は、現在の関数を識別する。フィールド「ｃｕｒｒｅｎｔ  ｆｕｎｃｔｉｏｎ」２１０６は、現在の関数を一意に識別する、現在処理されている構文解析ツリー構造３０４内のノードを指し示すポインタである。フィールド「ｃｕｒｒｅｎｔ  ｉｔｅｒａｔｉｏｎ」２１０８は、分析された現在の関数中のパスの数のカウントを指す。フィールド「ｃｕｒｒｅｎｔ  ｓｔａｔｅｍｅｎｔ」２１１０は、現在分析されている文を識別する、現在処理されている構文解析ツリー構造３０４内のノードを指し示すポインタである。フィールド「ｃｕｒｒｅｎｔ  ｌｉｎｅ  ｎｕｍｂｅｒ」２１１２は、現在分析されている文を含むフィールド「ｆｉｌｅｎａｍｅ」２１０２のソース・ファイル内の行を識別する。フィールド「ｃｕｒｒｅｎｔ  ｅｘｐｒｅｓｓｉｏｎ」２１１４は、現在分析されている式を識別する、現在処理されている構文解析ツリー構造３０４内のノードを指し示すポインタである。フィールド「ｅｍｕｌａｔｉｏｎ  ｄｅｐｔｈ」２１１６は、フィールド「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」２１１４内の関数の入れ子にされた関数呼出しの深さである。フィールド「ｅｍｕｌａｔｉｏｎ  ｃｏｎｔｅｘｔ  ｌｉｓｔ」２１１８は、入れ子にされた関数呼出しで呼び出される各関数に関するコンテキスト情報の集合である。関数呼出しが「入れ子にされる」のは、その関数呼出しが他の関数呼出しの引数として使用されるか、あるいはそれ自体の引数の１つとして他の関数呼出しを使用するときである。フィールド「ｅｍｕｌａｔｉｏｎ  ｄｅｐｔｈ」２１１６および「ｅｍｕｌａｔｉｏｎ  ｃｏｎｔｅｘｔ  ｌｉｓｔ」２１１８が意味を持つのは、現在分析されている式が関数呼出しであるときだけである。
アクション１１０２は、「ｆｉｌｅｎａｍｅ」２１０２、「ｆｕｎｃｔｉｏｎ  ｎａｍｅ」２１０４、「ｃｕｒｒｅｎｔ  ｆｕｎｃｔｉｏｎ」２１０６を設定する。本発明の一実施形態では、あるルーチンを使用して、実行コンテキストブロック２１００の最初の３つのフィールドが初期設定される。マイクロフィッシュの付録Ａの実施形態では、「ｃｔｘ＿ｂｅｇｉｎ＿ｆｕｎｃｔｉｏｎ」と呼ばれるルーチンが実行コンテキストブロック２１００の最初の３つのフィールドを初期設定する。関数ごとデータ構造が割り付けられるか、あるいは初期設定され、グローバル・データ構造が関数レベル情報で更新された後、処理は構文解析ツリー構造ロードアクション１１０４へ移る（以下では「アクション１１０４」と呼ぶ）。
アクション１１０４は、現在の関数を表す構文解析ツリー構造３０４をメモリに読み込む。処理は、アクション１１０４からパス分析アクション１１０８（以下では「アクション１１０８」と呼ぶ）へ移る。
アクション１１０８は、現在の関数全体にわたる複数のコード・パスをシミュレートされた実行を追跡することによって現在の関数を分析する。アクション１１０８は、最大パス数に達するか（ｍａｘｉｍｕｍ＿ｐａｔｈオプションが設定されている場合）、あるいはもはや実行するコードがなくなるまで、コード・パスを実行し続ける。ｍａｘｉｍｕｍ＿ｐａｔｈオプションは、ユーザが、各関数に対して実行される分析の量の限界を設定することを可能にする。ｍａｘｉｍｕｍ＿ｐａｔｈオプションを設定すると、（現在の関数内のいくつかのコード・パスがトラバースされていない場合でも）分析されるパスの数の上限が設定される。アクション１１０８は、最初に実行すべきパスを見つけるループを実行し、次いでこのパスを実行する。
アクション１１０８は、決定的選択点履歴を使用してパスを見つける。関数の実行は、選択点ノードと選択エッジからなる選択点履歴（ＣＰＨ）ツリーとしてモデル化される。ＣＰＨツリーは、第５図に示した構文解析ツリーと同様に構造のツリーである。ＣＰＨツリーのルート・ノードは、現在の関数中の第１の未処理の選択点であり、リーフ・ノードは関数リターンおよび関数終了である。前述のように、選択点とは、条件または述語の値に基づいて２組以上の代替プログラム文のうちの１組の間で選択が行われるプログラム内の点である。選択点ノードは、分析エンジン３０８が、処理するのに十分な情報を有さない選択点に対応する。選択点ノードは、現在の関数内の未処理の選択点に対応する構文解析ツリー構造３０４内のノードを指し示すポインタを含む。選択エッジは、選択点のいくつかの異なる可能な処理に対応する。たとえば、相等性に関する試験では真と偽のどちらかが判定される。選択点ノードは相等性試験に対応する。この特定の選択点ノードは２つの選択エッジを有する。一方の選択エッジは「真」結果に対応し、一方は「偽」結果に対応する。
選択点履歴は、各パスが複製可能であるという点で決定性である。コードのいくつかの異なる実行において未処理の各選択点を同様に処理する場合、コード内の同じパスをたどる。各選択点ノードは、固定数の選択エッジを有する。これは、未処理の選択点ノードから延びるパスの数が固定されることを意味する。この数は、実行の前には未知であるが、選択点ノードに関する選択を初めて行うときに決定される。現在の関数を実行する前にはＣＰＨツリー構造全体が未知である。ＣＰＨツリーは、現在の関数を分析する間に動的に構築される。
ＣＰＨツリーは、修正幅優先構築方法を使用したプログラム実行中に構築される。アクション１１０８は「現在レベル」値を維持する。現在レベル値は、ＣＰＨツリーにどの選択点が追加されたかを示す。任意の所与の時間には、現在のレベルよりも１つ以上上のレベルであるＣＰＨツリーのすべてのノードが処理されている。したがって、これらのノードのすべての選択エッジが決定される。
アクション１１０８は、現在のレベルよりも１つ上のレベルであるノードから出てルート・ノードに戻る未処理の選択エッジを無作為に選択することによって、新しいパスを選択する。このように、アクション１１０８は、ルート・ノードから始まるパスを決定し、現在のレベルよりも１つ上のレベルの選択されたノードまでＣＰＵツリーをトラバースする。現在のレベルよりも１つ上のレベルのノードから出る未処理の選択エッジが見つからない場合、現在レベル値が１だけ増加され、ステップが繰り返される。現在レベル値を増加させることは、分析がＣＰＨツリー内で１レベル下に移動したことを意味する。現在レベル値が増加され、現在のレベルよりも１つ上のレベルのノードから出る未処理の選択エッジが依然としてない場合、もはやパスを見つけることはできない。本発明の一実施形態では、あるルーチンによって新しいパスが決定される。マイクロフィッシュの付録Ａの実施形態では、「ｃｐｈ＿ｐａｔｈ＿ｆｉｎｄ」ルーチンが新しいパスを決定する。
各パスが決定されるたびに、アクション１１０８はメモリ・モデルを作成し、コード・パスに沿った命令のメモリ・モデルに対する効果をシミュレートし、コード・パス上の関数呼出しをエミュレートし、エラーを検出した時点で障害インジケータ１０６を生成し、現在の関数のモデル１１８を構築するのに必要な情報を収集する。このパスごと処理については以下で詳しく説明する。処理はアクション１１０８から関数外部動作モデル収集アクション１１１０（以下では「アクション１１１０」と呼ぶ）へ移る。
アクション１１１０は、将来モデル作成時に使用される現在の関数の外部動作モデルを収集する。アクション１１１０は、収集した外部動作モデルをグローバル変数に変換する。以後の処理時に、モデル作成ルーチンがグローバル変数からこのような外部動作モデルを抽出する。関数外部動作モデルとは、関数の外部で参照することができるか、あるいはいくつかの関数呼出しにわたって持続する値、すなわち局所静的変数を有する関数内のオブジェクトである。関数外部動作モデルの最も一般的な２つの例はパラメータと返却値である。現在の関数の外部動作モデルが記録された後、処理はアクション１１１０から構文解析ツリー構造解放アクション１１１２（以下では「アクション１１１２」と呼ぶ）へ移る。
アクション１１１２は、現在の関数を表す構文解析ツリー構造３０４を解放する。現在の関数を表す構文解析ツリー構造３０４を必要なくなった時点で解放することによって、メモリ資源を効率的に使用することができる。本発明の一実施形態では、アクション１１１２はあるルーチンによって実行される。マイクロフィッシュの付録Ａの実施形態では、ルーチン「ｍｃｉｌ＿ｒｅｌｅａｓｅ＿ｍｅｍｏｒｙ＿ｒｅｇｉｏｎ」が構文解析ツリー構造３０４を解放する。処理はアクション１１１２から関数ごとデータ構造クリーンナップアクション１１１４（以下では「アクション１１１４」と呼ぶ）へ移る。
関数ごと処理はアクション１１１４で終了し、関数ごとに使用される記憶域がクリーンナップされる。本発明の一実施形態では、ルーチンを使用して、パッケージ内の関数ごとデータ構造が解放またはクリーンナップされる。このルーチンは、ｅｘｅ、ａｕｔｏ、ｃｐｈ、ｉｎｓ、ｓｙｍ、ｖｉｍ、ｅｒｒ、ｍｃｉｌ、ｅｘｅのパッケージ順で呼び出される。特に、それぞれのａｕｔｏパッケージ・ルーチンは現在の関数のモデル１１８を作成する。オートモデル化については以下で詳しく説明する。マイクロフィッシュの付録Ａの実施形態では、「ｐｋｇ＿ｅｎｄ＿ｆｕｎｃｔｉｏｎ」（「ｐｋｇ」はパッケージの名前を表す）というラベルの付いたルーチンが、関数ごとに使用される記憶域をクリーンナップまたは解放する。たとえば、ｖｉｍパッケージ内の関数ごとデータ構造は、「ｖｉｍ＿ｅｎｄ＿ｆｕｎｃｔｉｏｎ」というラベルの付いたルーチンによって解放される。「ｐｋｇ＿ｅｎｄ＿ｆｕｎｃｔｉｏｎ」ルーチンは、「ｐｋｇ＿ｂｅｇｉｎ＿ｆｕｎｃｔｉｏｎ」ルーチンの逆の順序で呼び出される。アクション１１１４が完了すると、関数ごと処理が終了する。
パスの分析
前述のように、アクション１１０８は、複数のシミュレートされた実行のコード・パスを追跡することによって現在の関数を分析する。アクション１１０８は、分析する各パスごとに１回ずつ、現在の関数を表す構文解析ツリー構造３０４（以下では、「現在の構文解析ツリー構造３０４」と呼ぶ）をトラバースする。アクション１１０８は、分析する各パスについて、ブロック図１２００（第１２図）に示したようにパスごと処理を実行する。分析中のパスは現在のパスとして指定される。パスごと処理は、プログラム読取りアクション１２０２（以下では「アクション１２０２」と呼ぶ）から始まる。
アクション１２０２は、現在の関数に関してプラグマが定義されているかどうかを判定する。プラグマとはＩｎｔｒｉｎｓａ指令であり、プラグマの直後の関数または文の制御を設定する。ユーザは、関数のソース・コードにＩｎｔｒｉｎｓａプラグマを埋め込むことによって構成オプションを指定することができる。関数の直前に配置されたプラグマは、関数全体に適用される。たとえば、以下のプラグマは、主関数のすべての文に適用される。
0004633203.tif 000004
「抑制（ｓｕｐｐｒｅｓｓ）」構成オプションの詳細は、付録Ｂに記載されている。
アクション１２０２は、プラグマを見つけるとまず、プラグマによって指定された構成オプションの現在の設定を保存し、次いでプラグマに指定された値に応じてこのような構成オプションを設定する。処理はアクション１２０２からパスごとデータ構造初期設定アクション１２０４（以下では「アクション１２０４」と呼ぶ）へ移る。
アクション１２０４は、パスごとに使用されるデータ構造を割り付けるか、あるいは初期設定する。第１２図の実施形態では、あるルーチンを実行することによって、パッケージ内のパスごとデータ構造が割り付けられるか、あるいは初期設定される。このようなルーチンは、ｃｔｘ、ｍｃｉｌ、ｅｒｒ、ｖｉｍ、ｓｙｍ、ｉｎｓ、ｃｐｈ、ａｕｔｏ、ｅｘｅのパッケージ順で呼び出される。マイクロフィッシュの付録Ａの実施形態では、アクション１２０４で実行されるルーチンには「ｐｋｇ＿ｂｅｇｉｎ＿ｐａｔｈ」（「ｐｋｇ」はパッケージの名前を表す）というラベルが付けられる。たとえば、ｓｙｍパッケージ内のパスごとデータ構造は、「ｓｙｍ＿ｂｅｇｉｎ＿ｐａｔｈ」というラベルの付いたルーチンによって割り付けられる。
チャンク・テーブルは、アクション１２０４によって作成されるパスごとデータ構造の例である。チャンク・テーブルは、１組のすべてのモデル化メモリを含み、記憶域管理とリーク検出のために使用される。本発明の一実施形態では、チャンク・テーブルは、チャンクを指し示すポインタの集合としてインプリメントされる。チャンクとは既知のメモリのモデル化された部分であり、これについては以下で詳しく説明する。概念的には、追跡されるあらゆるパスは関数の異なる実行であり、したがって、各実行をサポートするために新しいメモリ・モデルが作成される。本発明の一実施形態では、チャンク・テーブルはあるルーチンによって作成される。マイクロフィッシュの付録Ａの実施形態では、「ｖｉｍ＿ｂｅｇｉｎ＿ｐａｔｈ」ルーチンがチャンク・テーブルを作成する。
アクション１２０４によって作成される他のパスごとデータ構造は記号テーブルである。記号テーブルは、名前（「記号」）を含む構文解析ツリー・ノードをメモリ・モデル内の位置と関連付ける。記号テーブルとは、記号テーブル・エントリ１３００を指し示すポインタの集合である。各記号テーブル・エントリ１３００は、現在の関数で使用される変数に対応する。
記号テーブル・エントリ１３００を第１３図に示す。記号テーブル・エントリ１３００は、「ｐａｒｓｅ  ｔｒｅｅ  ｐｏｉｎｔｅｒ（構文解析ツリー・ポインタ）」１３０２、「ｓｙｍｂｏｌ  ｔｙｐｅ（記号タイプ）」１３０４、「ｍｅｍｏｒｙ  ｔｙｐｅ（メモリ・タイプ）」１３０６、「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ（記号位置）」１３０８、「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ  ｐｏｉｎｔｅｒ（記号位置ポインタ）」１３１０、「ｐａｒｅｎｔ  ｉｎｄｅｘ（親インデックス）」１３１２の各フィールドを含む。メモリ・モデル内の位置については以下で詳しく説明する。
フィールド「ｐａｒｓｅ  ｔｒｅｅ  ｐｏｉｎｔｅｒ」１３０２は、記号テーブル・エントリ１３００によって表される記号を定義する現在の構文解析ツリー構造３０４内のノードを指し示す。フィールド「ｓｙｍｂｏｌ  ｔｙｐｅ」１３０４は、記号テーブル・エントリ１３００によって表される記号の種類を識別する。本発明の一実施形態では、フィールド「ｓｙｍｂｏｌ  ｔｙｐｅ」１３０４の可能な値は「変数」、「定数」、「ルーチン」、「差」、「返却値」である。フィールド「ｍｅｍｏｒｙ  ｔｙｐｅ」１３０６は、記号テーブル・エントリ１３００によって表される記号の値を保持するために使用されるメモリの種類を記述する。メモリ・タイプについては以下で詳しく説明する。
フィールド「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ」１３０８は、記号テーブル・エントリ１３００によって表される記号の値を記憶するチャンクを指し示すコード化ポインタである。コード化ポインタについては以下で詳しく説明する。フィールド「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ  ｐｏｉｎｔｅｒ」１３１０は、「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ」１３０８によって指し示されるチャンクのコード化ポインタを記憶するチャンクのコード化ポインタ（すなわち、記述中の記号の値を指し示すポインタ）である。フィールド「ｐａｒｅｎｔ  ｉｎｄｅｘ」１３１２は差のためだけに使用される。差とは、ポインタによって指し示される値を指す。記号テーブル・エントリが微分値を表すとき、フィールド「ｐａｒｅｎｔ  ｉｎｄｅｘ」１３１２は、この微分値に到達するために使用されるポインタの記号テーブル内でのインデックスを保持する。たとえば、記号テーブル・エントリが*Ｐ（Ｐによって指し示される値）のエントリである場合、フィールド「ｐａｒｅｎｔ  ｉｎｄｅｘ」１３１２は、ポインタＰの記号テーブル内でのインデックスを含む。
アクション１２０４は、実行コンテキストブロック２１００に情報をポストする。アクション１２０６はフィールド「ｃｕｒｒｅｎｔ  ｉｔｅｒａｔｉｏｎ」２１０８内のカウントを１（このパスの数を示す）だけ更新する。処理は返却値レイアウトアクション１２０６（以下では「アクション１２０６」と呼ぶ）へ移る。
アクション１２０６は、現在の関数の返却値用のモデル化メモリをレイアウトする。アクション１２０６はまた、返却値を記号テーブルに入れる。まず、アクション１２０６は、返却値を表すのに必要なメモリの量を求める。この量、すなわち返却値の長さはバイト単位で測定される。次いで、アクション１２０６は、返却値を表すのに必要なメモリの量を用いてメモリ作成ユニット１５００を呼び出す。メモリ作成ユニット１５００は、返却値を保持するモデル化メモリの部分を作成し、メモリ・モデル内の新たに作成された位置を指し示すコード化ポインタをアクション１２０６に返す。メモリ作成ユニット１５００の動作については以下で詳しく説明する。次に、アクション１２０６は、作成された返却値位置を指し示すポインタをレイアウトする。第１２図の実施形態では、ポインタの長さは４バイトである。前述のように、アクション１２０６はメモリ作成ユニット１５００を呼び出し、モデル化メモリの適切なサイズの部分を作成し、新たに作成されたモデル・メモリ位置を指し示すコード化ポインタを受け取る。アクション１２０６は、返却値を指し示すポインタの位置に、返却値の位置のコード化アドレスを格納する。最後に、アクション１２０６は記号テーブルに返却値を入れる。
アクション１２０６は、記号テーブル・エントリ１３００を作成する。返却値を含む構文解析ツリー・ノードを指し示すポインタは、フィールド「ｐａｒｓｅ  ｔｒｅｅ  ｐｏｉｎｔｅｒ」１３０２内に置かれる。「変数」の記号タイプはフィールド「ｓｙｍｂｏｌ  ｔｙｐｅ」１３０２内に置かれる。「返却値」はフィールド「ｍｅｍｏｒｙ  ｔｙｐｅ」１３０６内に置かれる。返却値を保持するために作成された第１の位置を指し示すコード化ポインタは「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ」１３０８内に置かれる。返却値を指し示すポインタを格納するために作成された第２の位置を指し示すコード化ポインタはフィールド「ｓｙｍｂｏｌ  ｌｏｃａｔｉｏｎ  ｐｏｉｎｔｅｒ」１３１０内に置かれる。アクション１２０６では記号テーブルに記号差を格納することはないので、フィールド「ｐａｒｅｎｔ  ｉｎｄｅｘ」１３１２は使用されない。本発明の一実施形態では、あるルーチンによって記号テーブルに記号テーブル・エントリ１３００が入れられる。マイクロフィッシュの付録Ａの実施形態では、「ｓｙｍ＿ａｄｄ＿ｓｙｍｂｏｌ」というラベルの付いたルーチンが記号テーブルに記号テーブル・エントリ１３００を入れる。処理は、パスに沿った文の処理アクション１２０８（以下では「アクション１２０８」と呼ぶ）へ移る。
アクション１２０８は、現在のパスをトラバースし各文の実行を模倣する責任を負う。アクション１２０８は、個々の各文タイプの実行をシミュレートまたはエミュレートするのに適切な処理を実行する。アクション１２０８の処理についての詳細な議論は、以下に見出し「文の分析」の下で提示する。現在のパスに沿って各文を処理するアクション１２０８が終了した後、処理は記号テーブル順序付けアクション１２１０（以下では「アクション１２１０」と呼ぶ）へ移る。本発明の一実施形態では、アクション１２０８はあるルーチンによって実現される。マイクロフィッシュの付録Ａの実施形態では、「ｅｘｅ＿ｅｘｅｃｕｔｅ＿ｓｔａｔｅｍｅｎｔ」というラベルの付いたルーチンがアクション１２０８の関数を実行する。
アクション１２１０は、記号テーブルをソートし、分析エンジン３０８によってトラバースされる各パスに関する記号テーブル上の順序を同じにする。オートモデル化では、いくつかの異なるパスの結果を比較する必要がある。記号テーブルをソートすると、現在のパスを実行した結果を他のパスを実行した結果と比較するのが容易になる。本発明の一実施形態では、記号テーブルはアルファベット順にソートされる。
記号テーブルをソートする理由は例を介して最もうまく説明することができる。オートモデル化中には、後述のように、オートモデル化のために必要な記号テーブル内のあらゆる記号が調べられる。記号テーブル・エントリ１３００がポインタである場合は、ポインタ・チェーンをたどる。ポインタ・チェーンに沿った各位置は、チェーンの先頭にある記号の名前と、その前にある、この位置に到達するのに必要な各間接参照レベルについてのアスタリスク（「*」）とでラベル付けされる。たとえば、第１４ａ図を参照するとわかるように、ｐ１４１２は、「Ｌｏｃｌ」位置１４１６を指し示す記号テーブル１４１０内のポインタである。「Ｌｏｃ１」位置１４１６は、ポインタｐ１４１２から１間接参照レベルだけ離れており、「*ｐ」とラベル付けされる。「Ｌｏｃ１」位置１４１６は「Ｌｏｃ２」位置１４１８を指し示す。「Ｌｏｃ２」位置１４１８は、ポインタｐ１４１２から２間接参照レベルだけ離れており、「**ｐ」とラベル付けされる。
記号は、関数のパスに沿って記号に出会う順序で記号テーブル内に置かれる。関数のそれぞれの異なる経路をトラバースする際にそれぞれの異なる順序で記号に出会う。第１４ａ図では、コード・パス上でポインタｑ１４１４よりも前にポインタｐ１４１２に出会っており、したがって、ｐ１４１２は記号テーブル１４１０ではｑ１４１４よりも前にある。同じ関数中の異なる経路を表す第１４ｂ図では、ポインタｐ１４１２よりも前にポインタｑ１４１４に出会う。したがって、第１４ｂ図では、ｑ１４１４は記号テーブル１４２０でｐ１４１２よりも前に記録される。
ポインタｐ１４１２およびｑ１４１４は、値ゼロを含むメモリ・モデル位置１４２４（Ｌｏｃ２）を指し示す共用メモリ・モデル位置１４２２（Ｌｏｃ１）を指し示す。前述のラベル付けステップを第１４ａ図の記号テーブル１４１０に対して実行すると、結果は「*ｐ＝０」になる。この結果は、チェーンがポインタｐ１４１２から始まることに基づいて「Ｌｏｃ１」位置１４１６を*ｐとラベル付けすることから導かれる。ラベル付け演算を第１４ｂ図の記号テーブル１４２０に対して実行すると、結果は「*ｑ＝０」になる。この結果は、チェーンがポインタｑ１４１４から始まることに基づいて位置１４２２「Ｌｏｃ１」を*ｑとラベル付けすることから導かれる。２つのパスは共に同じ実際の結果を有するが、式が異なる（「*ｐ＝０」と「*ｑ＝０」）ので、結果を併合することは難しい。
記号テーブルをソートすると、ポインタｐ１４１２は常にポインタｑ１４１４よりも前に処理される。このように、２つのパスは共に結果を「*ｐ＝０」として表す。記号テーブルを順序付けることによって、２つのパスの結果を単一の結果に併合することができる。したがって、記号テーブルを順序付けると、オートモデル化処理によって、いくつかの異なるパスの結果を容易に比較することができる。本発明の一実施形態では、あるルーチンによって記号テーブルが順序付けされる。マイクロフィッシュの付録Ａの実施形態では、ルーチン「ｓｙｍ＿ｏｒｄｅｒ＿ｔａｂｌｅ」が記号テーブルを順序付ける。処理はアクション１２１０からリーク検出アクション１２１２（以下では「アクション１２１２」と呼ぶ）へ移る。
アクション１２１２はリーク検出処理を実行する。アクション１２１２は、すべてのモデル化メモリを巡回し、現在のパスを分析する間に累積されたメモリ割付けに関する情報を走査する。アクション１２１２は、現在の関数が終了する際にリークするメモリのチャンクを識別する。割付け時にはメモリの一部がリークするが、このことが、関数が終了した後に記号によって指摘されることはない。アクション１２１２は、リークした資源も検出する。アクション１２１２によって実行される処理の詳細な説明は、以下に見出し「リーク検出」の下で与える。処理はアクション１２１２からｐｒａｇｍａ＿ｏｐｔｉｏｎリセットアクション１２１４（以下では「アクション１２１４」と呼ぶ）へ移る。
アクション１２１４は、アクション１２０２で設定された構成オプションを再生する。現在の関数にプラグマが定義されている場合、アクション１２１４は、このプラグマに指定されている構成オプションをアクション１２０２で保存された値に設定する。アクション１２１４は、処理をパスごとデータ構造解放またはクリーンナップアクション１２１６（以下では「アクション１２１６」と呼ぶ）へ移す。
パスごと処理はアクション１２１６で終了し、パスごとに使用される記憶域がクリーンナップされ、グローバル・データ構造が現在のパスに関する情報で更新される。第１３図の実施形態では、あるルーチンを実行することによって、パッケージ内のパスごとデータ構造が解放またはクリーンアップされる。このようなルーチンは、アクション１２０４で実行されるルーチンとは逆のパッケージ順で呼び出される。アクション１２１６によって呼び出されるルーチンは、ｅｘｅ、ａｕｔｏ、ｃｐｈ、ｉｎｓ、ｓｙｍ、ｖｉｍ、ｅｒｒ、ｍｃｉｌ、ｃｔｘのパッケージ順で呼び出される。マイクロフィッシュの付録Ａの実施形態では、アクション１２１６によって呼び出されるルーチンには「ｐｋｇ＿ｅｎｄ＿ｐａｔｈ」というラベルが付けられる。この場合、「ｐｋｇ」はパッケージの名前を表す。たとえば、ｅｘｅパッケージ内のパスごとデータ構造は、「ｅｘｅ＿ｅｎｄ＿ｐａｔｈ」というラベルの付いたルーチンによって解放される。ａｕｔｏパッケージに対応するアクション１２１６によって実行されるルーチンは、現在のパスの「実行」に関する情報を収集し、現在の関数のモデル１１８を作成する際に助けとなるので特に重要である。オートモデル化については以下で詳しく説明する。アクション１２１６が完了すると、パスごと処理が終了する。
メモリ作成ユニット１５００
前述のように、メモリ作成ユニット１５００は、メモリをモデル化するために必要なデータ構造を作成する。分析エンジン３０８によって作成されたメモリ・モデルは、実行中にプログラムが使用するメモリを表している。分析エンジン３０８は構造上のメモリ・モデルを作成する。というのは、そのモデルは値ではなく値の内部合成物（ｃｏｍｐｏｓｉｔｉｏｎ）を単一ユニットとして模倣するからである。たとえば、Ｃ言語プログラムを分析する本発明の一実施形態では、倍長整数は、１つの単一アドレス可能値とは対照的に、個々にアドレス可能な４バイトの合成物として表されている。しかし、メモリ・モデルは、一時値を格納するために多くのコンピュータ・プログラムが使用するヒープ記憶域のように、物理的に隣接しているわけではない。
メモリ・モデルは、チャンク（ｃｈｕｎｋ）・テーブルと、チャンク１７００と、ポインタによってまとめてリンクされた格納値１８００から構成される。前述のように、チャンク・テーブルはモデル化メモリのすべてを記録する。チャンク１７００は、１つまたは複数の隣接メモリ位置をモデル化する。格納値１８００は、１つまたは複数のメモリ位置（すなわち、チャンク１７００）に格納された値を保持する。チャンク１７００および格納値１８００については以下に詳述する。メモリ作成ユニット１５００の処理は、起点情報収集アクション１５０２（以下「アクション１５０２」という）から始まる。
アクション１５０２は、メモリが作成されるコンテキストを追跡するものである。アクション１５０２は、メモリ作成ユニット１５００が処理を開始したときにコンテキスト情報をカプセル化する起点コンテキスト構造１６００を作成する。起点コンテキスト構造１６００は、後述するようにチャンク１７００に格納される。起点コンテキスト構造については第１６図に示す。起点コンテキスト構造１６００は、「外部ＩＤタイプ」１６０２と、「外部ＩＤ」１６０４と、「メモリ・タイプ」１６０６と、「ステートメントの作成元」１６０８と、「式の起点」１６１０と、「エミュレーション中フラグ」１６１２と、「ソース・コード・ファイル」１６１４と、「ソース行番号」１６１６と、「入力名」１６１８と、「出力名」１６２０というフィールドを含む。
フィールド「外部ＩＤタイプ」１６０２は、その記憶域が作成された項目のタイプを示す。本発明の一実施形態で可能な項目タイプは、「記号」、「格納値」、「文字列」、「戻り値」、「未知」である。「格納値」については後述するが、「未知」は項目タイプを決定できないことを意味する。「記号」および「文字列」というタイプの項目は、当業者には周知のものである。フィールド「外部ＩＤ」１６０２は、モデル化したメモリの作成をトリガする項目を明確に識別する現行構文解析ツリー構造３０４内のノードを指すポインタを含む。
フィールド「メモリ・タイプ」１６０６は、何のためにそのメモリが作成されるのかを分類する。以下に詳述するように、フィールド「メモリ・タイプ」１６０６はモデル化のために使用する。その関数の外部で可視の項目のためにメモリを作成している場合、それは自動モデル化の際に使用されることになる。本発明の一実施形態では、モデル化したメモリのタイプは、定数、グローバル、グローバルのデリファレンス、スタティック、スタティックのデリファレンス、ローカル、パラメータ、パラメータのデリファレンス、ヒープ・メモリ、資源定義、資源、一時、未知、アドレス定数、文字定数、ゼロ定数である。当業者であれば、定数、グローバル、ローカル、スタティック、パラメータ、戻り値の各項目については分かるだろう。
前述のように、デリファレンスとは、ポインタが指し示す値を意味する。たとえば、グローバルのデリファレンスは、グローバル変数が指し示す値を保持するメモリ位置を示す。「未知」というメモリ・タイプは、モデル化したメモリの区画がその関数の外部で可視ではないことを示す。メモリ・タイプが「未知」の項目は、現行関数用のモデル１１８を作成する際に使用しない。一時値は、現行関数が実行する計算の中間ステップから得られ、現行構文解析ツリー構造３０４で識別される。ヒープ・メモリは現行関数が割り振ったメモリである。たとえば、Ｃ言語の「ｍａｌｌｏｃ（１０）」という関数呼出しは１０バイトのヒープ・メモリを作成する。資源および資源定義は、ファイルおよびウィンドウなど、関数が使用するオブジェクトを示す。
より一般的な「定数」メモリ・タイプは、分析エンジン３０８内の処理の最適化を見込んでおくために、アドレス、文字、文字列定数という特定のケースとは区別される。ゼロは頻繁に使用される数なので、分析エンジン３０８は、現行関数で使用するたびに定数ゼロのインスタンスを１つだけモデル化する。他の定数タイプとは対照的に、アドレス定数だけがデリファレンスされるので、リーク検出処理が改善される。項目が有効ポインタであるかどうかを判定するチェックは、文字定数については行う必要がないので、全体的な効率が改善される。最適化されたメモリ管理および意志決定によって、分析エンジン３０８のパフォーマンスが改善される。
フィールド「ステートメントの作成元」１６０８は、フィールド「外部ＩＤ」１６０４で識別された項目を含むステートメントを識別する現行構文解析ツリー構造３０４内の構文解析ツリー・ノードを指すポインタである。フィールド「式の起点」１６１０は、フィールド「外部ＩＤ」１６０４で識別された項目を含む式を識別する現行構文解析ツリー構造３０４内の構文解析ツリー・ノードを指すポインタである。フラグ「エミュレーション中フラグ」は、モデル化メモリがモデル１１８の実行のために作成されるときに真になる。フィールド「ソース・コード・ファイル」１６１４は、現行関数を含むソース・コード・ファイルの名前を識別する。フィールド「ソース行番号」１６１６は、フィールド「ステートメントの作成元」１６０８によって識別されるステートメントのフィールド「ソース・コード・ファイル」１６１４によって識別されるソース・コード・ファイル内の行番号を識別する。フィールド「入力名」１６１８は、作成中のモデル化メモリの区画に関連する元の格納値の名前を含む。フィールド「出力名」１６２０は、作成中のモデル化メモリの区画に関連する最終値の名前を含む。フィールド「入力名」１６１８およびフィールド「出力名」１６２０は、モデル化しているメモリ位置が現行関数の開始時（「入力名」１６１８）または終了時（「出力名」１６２０）のいずれでアクセス可能であるかを記録するために自動モデル化プログラムによって使用される。起点コンテキスト構造１６００に適切に記入した後、処理はアクション１５０４に移行する。
アクション１５０４は、１つまたは複数の隣接メモリ位置用のモデルを作成するものである。メモリ位置は、アドレスによって明示的かつ明確に指定可能なメモリの最小単位である。通常、コンピュータ・メモリはバイト・アドレス可能であり、したがって、１つの位置は１バイトである。アクション１５０４は、チャンク１７００を使用してメモリをモデル化する。チャンク１７００については第１７図に示す。チャンク１７００は、「解放フラグ」１７０２と、「到達可能フラグ」１７０４と、「紛失フラグ」１７０６と、「メモリ・タイプ」１７０８と、「チャンク番号」１７１０と、「起点コンテキスト構造ポインタ」１７１２と、「格納値ポインタ」１７１４と、「元の格納値ポインタ」１７１６というフィールドを含む。
フラグ「解放フラグ」は、チャンク１７００によってモデル化されたメモリ位置が解放されたときに真になる。フラグ「到達可能フラグ」１３０２は、そのメモリ位置が到達可能であるかどうかを判定するためにリーク検出処理が使用する。フラグ「紛失フラグ」１７０６は、モデル化したメモリが解放されるかまたはリークされるかどうかを判定できないときに真になる。紛失メモリの場合、関数が終了したあとでメモリを指し示すものが何もない可能性があるが、メモリを指すポインタのレコードがないというだけで、このようなポインタが存在しないことを意味するわけではない。たとえば、欠落モデルによってモデル化されるルーチンにメモリを割り振って、渡すことができる。分析エンジン３０８は、ルーチンに渡された割振りメモリに何が起きたのかを確かめることができない。したがって、そのメモリは「紛失」としてマークされる。フィールド「メモリ・タイプ」１７０８は、前述のフィールド「メモリ・タイプ」１６０６と同じ情報を保持する。フィールド「チャンク番号」１７１０は、チャンク１７００用の固有の識別子である。フィールド「起点コンテキスト構造ポインタ」１７１２は、アクション１５０２で作成された起点コンテキスト構造１６００を指し示す。フィールド「格納値ポインタ」１７１４は、モデル化メモリ位置にある現行値を指し示す。フィールド「元の格納値ポインタ」１７１６は、モデル化メモリ位置にある元の値を指し示す。
まず、アクション１５０４は、チャンク１７００を再使用できるかどうかを判定するために、チャンク・テーブル内を反復してチャンク１７００を調べる。アクション１５０４がチャンク１７００を再使用できない場合、新しいチャンク１７００を作成しなければならない。新しいチャンク１７００を指すポインタはチャンク・テーブル内に配置される。チャンク番号１７１０には、新しいチャンク１７００を明確に識別する番号が割り当てられる。フラグ「解放フラグ」１７０２、「到達可能フラグ」１７０４、「紛失フラグ」１７０６は、偽に初期設定される。フィールド「メモリ・タイプ」１７０８は、アクション１５０２で設定された「メモリ・タイプ」１６０６と等しくなるように設定される。フィールド「起点コンテキスト構造ポインタ」１７１２は、アクション１５０２で構築された起点コンテキスト構造１７００を指し示すように設定される。次に処理は、格納値セットを作成するために値モデル化アクション１５０６（以下「アクション１５０６」という）に移行する。
アクション１５０６は、アクション１５０４で作成したチャンク１５００によってモデル化された位置に配置された値をモデル化するものである。メモリ作成ユニット１５００は、格納値セットを作成することによって値をモデル化する。格納値セットは格納値の集合である。各格納値は、１単位分のメモリを表すデータ構造である。第１５図の実施形態では、メモリ作成ユニット１５００は、Ｃコンピュータ言語のメモリ管理特性を模倣する。Ｃコンピュータ言語は、隣接バイト・セットとして値を割り振る。各格納値は１バイト分のメモリを表す。したがって、１セット分の格納値は、１つの値を格納するために使用するバイトの集合を表す。たとえば、正規整数は、通常、長さ４バイトである。アクション１５０６は、４つの格納値を作成し、それを格納値セット内に配置することによって整数をモデル化する。
アクション１５０６は、作成中のメモリの各バイトごとに１つの格納値を作成する。作成した各格納値を指すポインタは格納値セット内に配置される。したがって、格納値セットは、格納値を指すポインタの集合になる。格納値は、格納値ブロック１８００によって表される。格納値ブロック１８００については第１８図に示す。格納値ブロック１８００は、「起点ポインタ」１８０２と、「資源フラグ」１８０４と、「正確値既知フラグ」１８０６と、「初期設定済みフラグ」１８０８と、「想定値フラグ」１８１０と、「制約フラグ」１８１２と、「結果フラグ」１８１４と、「保護フラグ」１８１６と、「正確値」１８１８と、「入力からのバイト」１８２０と、「出力からのバイト」１８２２というフィールドを含む。
フィールド「起点ポインタ」１８０２は、アクション１５０２で作成した起点コンテキスト構造１６００を指し示す。フラグ「資源フラグ」１８０４は、このデータ構造が格納値または格納資源のいずれを表すかを識別する。フラグ「資源フラグ」１８０４は、データ構造が格納値を表す場合に必ず偽になる。資源は格納値と同様に表されるが、格納値ブロック１８００の代わりに格納資源ブロック１９００を使用する。格納資源ブロック１９００については後述する。フラグ「正確値既知フラグ」１８０６は、フィールド「正確値」１８１８が有効値を含むときに真になる。フラグ「想定値フラグ」１８１０は、この値が処理中に想定された場合に真になる。フラグ「制約フラグ」１８１２は、モデル１１８内の制約でこの値を使用できる場合に真になる。フラグ「結果フラグ」１８１４は、モデル１１８内の結果でこの値を使用できる場合に真になる。フラグ「保護」は、モデル１１８内の保護でこの値を使用できる場合に真になる。制約、結果、保護については「概念のモデル化」という見出しの項で詳述する。フィールド「正確値」１８１８は、モデル化メモリ位置に格納された正確値を含む。フィールド「入力からのバイト」１８２０は、この格納値に対応する（「元の格納値ポインタ」１７１６が指し示す）元の格納値セット内の特定のバイトを識別する。フィールド「出力からのバイト」１８２２は、この格納値に対応する（「格納値ポインタ」１７１４が指し示す）最終格納値セット内の特定のバイトを識別する。
あるいは、資源用のメモリをモデル化するためにメモリ作成ユニット１５００を呼び出す場合、アクション１５０６は、格納資源ブロック１９００を作成することになる。格納資源ブロック１９００については第１９図に示す。格納資源ブロック１９００は、「起点ポインタ」１９０２と、「資源フラグ」１９０４と、「リーク可能フラグ」１９０６と、「到達可能フラグ」１９０８と、「紛失フラグ」１９１０と、「想定フラグ」１９１２と、「資源タイプ」１９１４と、「資源状態」１９１６というフィールドを含む。
フィールド「起点ポインタ」１９０２は、アクション１５０２で作成した起点コンテキスト構造１６００を指し示す。フラグ「資源フラグ」１９０４は、このデータ構造が格納値または格納資源のいずれを表すかを識別する。フラグ「資源フラグ」１９０４は、データ構造が格納資源を表す場合に必ず真になる。フラグ「リーク可能フラグ」１９０６は、現行関数が終了したあとで資源を指し示すことができないときに真になる。フラグ「到達可能フラグ」１９０８は、後述するようにリーク検出処理の際に使用する。フラグ「紛失フラグ」１９１０は、現行関数が終了したあとで資源を指し示すかどうかを分析エンジン３０８が予測できないことを示す。フラグ「想定フラグ」１９１２は、分析エンジン３０８での処理中に資源が想定されたときに真になる。フィールド「資源タイプ」１９１４および「資源状態」１９１６は、モデル化メモリを必要とする資源のタイプと状態をそれぞれ保持する。必要な数の格納値ブロック１８００または格納資源ブロック１９００が作成され、格納値セット内に配置された後、処理はメモリ位置と値とのリンク・アクション１５０８（以下「アクション１５０８」という）に移行する。
アクション１５０８は、モデル化値（または資源）をモデル化メモリ位置にリンクするものである。これがチャンク１７００について第１の格納値セットである場合、格納値ポインタ１７１４と元の格納値ポインタ１７１６の両方は、アクション１５０４で作成した格納値セットを指し示すように設定される。そうではない場合、格納値ポインタ１７１４だけが、アクション１５１４で作成した格納値セットを指し示すように設定される。このようにして、１つの位置に関する元の格納値セットと、１つの位置に関する最新格納値セットがチャンク１７００に記憶される。格納値の中間インスタンスは自動モデル化には必要ないので廃棄される。モデル１１８は、関数が求める結果を記述するものであって、結果に到達する方法を記述するものではない。したがって、中間インスタンスではなく、格納値の初期インスタンスと最終インスタンスだけが、自動モデル化のために検査される。
メモリ作成ユニット１５００用の処理は終了し、アクション１５０８はメモリ作成ユニット１５００の呼出し側に新たにモデル化したメモリを指す符号化ポインタを返す。符号化ポインタは、チャンク１７００を指すポインタと、格納値ポインタ１７１２が指し示す格納値セットへのオフセットからなる。モデル化メモリ内の位置はシミュレートしたメモリ位置なので、符号化ポインタが必要になる。たとえば、第２０図に示すようにメモリをモデル化するために使用するデータ構造間のリンクの簡略図を参照されたい。チャンク２００４は、チャンク・テーブル２００２内の項目によって配置される。次にチャンク２００４は、関連の格納値セット２００６を指すポインタを含む。格納値セット２００６へのオフセットは、格納値２００８、２０１０、２０１２を指すポインタである。したがって、モデル化メモリ内では、真のメモリ位置とは異なり、単純な物理アドレスによって値にアクセスすることができない。このため、モデル・メモリ位置、またはより単純に位置は、格納値ブロック１８００を指す符号化ポインタになる。
リーク検出
前述のように、リークは、パス内のステートメントが処理されたあとでパス分析の終わりにアクション１２１２で検出される。メモリ・リークは、マーク・スウィープ方法を使用して検出される。まず、アクション１２１２は、チャンク・テーブル内を反復し、各チャンクを到達不能としてマークする。チャンク１７００は、フラグ「到達可能フラグ」１７０４を偽に設定することによって到達不能としてマークされる。次に、アクション１２１２は、記号テーブル内の各外部内を反復し、ポインタ連鎖のみを移動する。アクション１２１２は、ポインタ連鎖内で検出された各チャンク１７００を到達可能としてマークする。チャンク１７００は、フラグ「到達可能フラグ」１７０４を真に設定することによって到達可能としてマークされる。記号テーブルを処理した後、アクション１２１２は、チャンク・テーブル内を反復して各チャンク１７００を検査する。各チャンクごとに、それがヒープ記憶域であって、解放も紛失もされておらず、依然として到達不能としてマークされている場合、そのチャンクはリーク済みとして報告される。本発明の一実施形態では、メモリ・リークは、対応する故障インジケータ１０６によって報告される。
また、アクション１２１２は資源リークも報告する。チャンク・テーブル内でもう一度反復が行われるが、今回のアクション１２１２は、資源を示すようにフィールド「メモリ・タイプ」１７０８が設定されたすべてのチャンク１７００をサーチする。資源を定義する各チャンクごとに、対応する格納資源ブロック１９００に対して問合せを行う。資源が到達可能ではなく、認識された状態の１つになっていない場合、それはリーク済みとして報告される。認識された状態としては、閉、解放、リリース済み、削除済みがある。本発明の一実施形態では、資源リークは対応する故障インジケータ１０６によって報告される。
ステートメント分析
アクション１２０８は、前述のように、現行パスに沿って各ステートメントの実行の模倣を担当する。分析中の現在のステートメントを現行ステートメントと称する。アクション１２０８は、さらに処理するために現行ステートメントを識別し、分散する。アクション１２０８については第２２図のブロック図に示す。アクション１２０８用の処理は、プラグマ読取りアクション２２０２（以下「アクション２２０２」という）から始まる。
アクション２２０２は、現行ステートメント用にプラグマが定義されているかどうかを判定するものである。前に提示したように、プラグマは、プラグマの直後の関数またはステートメントに関する制御を設定するＩｎｔｒｉｎｓａ指示文である。ステートメントの直前のソース・コード内に配置されたＩｎｔｒｉｎｓａプラグマは、その特定のステートメントのみを制御するための構成オプションを指定する。たとえば、以下のプラグマは、「ａ＝１＋２；」というステートメントのみに適用される。
＃ｐｒａｇｍａ  ＩＮＴＲＩＮＳＡ  “ｓｕｐｐｒｅｓｓ＝ｎｕｌｌ＿ｐｏｉｎｔｅｒ，  ｕｎｉｎｉｔｉａｌｉｚｅｄ”
ａ＝１＋２；
ｂ＝ａ；
「ｓｕｐｐｒｅｓｓ」構成オプションに関する詳細は付録Ｂに記載されている。アクション２２０２は、プラグマを検出した場合、まず、プラグマによって指定された構成オプションの現行設定を保管し、次に、プラグマ内に指定された値に応じてこれらの構成オプションを設定する。処理は、アクション２２０２からコンテキスト情報更新アクション２２０４（以下「アクション２２０４」という）に移行する。
アクション２２０４は、実行コンテキスト・ブロック２１００にコンテキスト情報を通知するものである。現行ステートメント２１１０は、現行ステートメントを表す現行構文解析ツリー構造３０４内のノードを指し示すように設定される。現行行番号２１１２は、現行ステートメントを含む現行関数を格納するファイル内の行番号に設定される。処理は、アクション２２０４から個々のステートメント・タイプに基づく直接処理アクション２２０６（以下「アクション２２０６」という）に移行する。
アクション２２０６は、さらに処理するためにステートメント・ユニットに分散することにより、個々のステートメントを処理するものである。アクション２２０６は、まず、分析中のステートメントのタイプを識別する。次にアクション２２０８は、処理制御を対応するステートメント・ユニットに移転する。第２２図の実施形態に関して、表３は、ステートメントのタイプと呼び出されたステートメント・ユニットとの対応関係を示している。「ステートメント・ユニット」という列に列挙したモジュールについては以下に詳述する。「ステートメント・タイプ」という列に列挙したステートメント・タイプは、当業者にとって周知ものである。制御がアクション２２０６に戻ると、処理は、プラグマ・オプション・リセット・アクション２２０８（以下「アクション２２０８」という）に移行する。
0004633203.tif 000005
アクション２２０８は、アクション２２０２で設定した構成オプションを復元するものである。現行ステートメント用にプラグマが定義されている場合、アクション２２０８は、プラグマ内に指定された構成オプションをアクション２２０２で保管した値に設定する。アクション２２０８は処理制御を開始アクション制御に返す。
次にステートメント・ユニットの説明に移行すると、ブロック・ユニットは、ブロック・ステートメント内のステートメントによるループを実行する。ブロック・ステートメントは、しばしば複文と呼ばれるが、１つの構文ユニットを形成する１組のステートメントである。通常、ブロック・ステートメントは、Ｃプログラミング言語で書かれた関数内の最高レベルのステートメントである。ブロック・ユニットについては、論理流れ図２３００（第２３図）として詳細に示す。
パス終了判断２３０１（以下「判断２３０１」という）では、現在のブロックが終了したかどうかを確認するためにチェックを行う。ｎｕｌｌまたはｅｘｉｔステートメントが前に処理されている場合、現行ブロック・ステートメントの分析は完了し、論理流れ図２３００による処理、したがって、ブロック・ユニットは終了する。現在のブロックが依然として活動状態である場合、処理は、ｇｏｔｏステートメントが処理されているかどうかを判定するｇｏｔｏケース判断２３０２（以下「判断２３０２」という）に移行する。第２３図の実施形態では、ｇｏｔｏ処理は、ｇｏｔｏパラメータに問い合わせることによって識別される。マイクロフィッシュの付録Ａの実施形態では、ｇｏｔｏパラメータは「ｇｏｔｏ＿ｓｔａｔｅｍｅｎｔ」と命名されている。ｇｏｔｏステートメントがシミュレートされることをｇｏｔｏパラメータが示している場合、処理はターゲット判断２３０３（以下「判断２３０３」という）に移行し、そうではない場合、処理制御はステートメント分析アクション２３０５（以下「アクション２３０５」という）に移行する。
判断２３０３は、活動ｇｏｔｏステートメントのターゲットであるステートメントに到達したかどうかを確認するためにテストを行う。判断２３０３は、ブロック内の現行ステートメントを表す現行構文解析ツリー・ノードを指すポインタと、ｇｏｔｏターゲット・ステートメントを表す現行構文解析ツリー・ノードを指すポインタとを比較する。２つのポインタが一致する場合、ブロック内の現行ステートメントはｇｏｔｏターゲット・ステートメントである。ｇｏｔｏターゲット・ステートメントに到達している場合、処理はｇｏｔｏ切断アクション２３０４（以下「アクション２３０４」という）に移行する。ブロック内の現行ステートメントがｇｏｔｏターゲット・ステートメントではない場合、処理は最終判断２３０６（以下「判断２３０６」という）に移行する。
アクション２３０４は、処理中の活動ｇｏｔｏステートメントがないことを示すためにｇｏｔｏパラメータを偽に設定する。アクション２３０４が完了した後、処理はアクション２３０５に移行する。アクション２３０５はブロック内の現行ステートメントを分析するものである。アクション２３０５は、ブロック内の現行ステートメントを表す現行構文解析ツリー構造３０４内のノードを指すポインタを取り出し、処理制御とともにそのポインタを再帰的にアクション１２０８に転送する。制御がアクション２３０５に戻ると、処理は最終判断２３０６に移行する。
判断２３０６は、現在のブロック・ステートメント内の最終ステートメントが処理されたかどうかを判定する。判断２３０６が真になる場合、論理流れ図２３００による処理、したがって、ブロック・ユニットは終了する。そうではない場合、最終ステートメントに到達していないので、処理は次の獲得アクション２３０９（以下「アクション２３０９」という）に移行する。アクション２３０９は、ブロック内の次のステートメントを獲得し、判断２３０１に制御を移転して、現在のブロック・ステートメントの処理を続行する。
式ユニットは式を処理するものである。入力として、式ユニットは、処理すべき式を表す現行構文解析ツリー構造３０４内のノードを指すポインタを受け取る。出力として、式ユニットは、式の結果を保持する位置を指すポインタを返す。「式」という用語は、本明細書では、ＫｅｒｎｉｇｈａｎおよびＲｉｔｃｈｉｅによるＴｈｅ  Ｃ  ｐｒｏｇｒａｍｍｉｎｇ  ｌａｎｇｕａｇｅ、１８５（Ｐｒｅｎｔｉｃｅ−Ｈａｌｌ、１９７８年）に定義されているように使用する。ステートメントは、セミコロンとともにそのあとに続くことによって、式から構築することができる。本発明の一実施形態では、式ユニットはルーチンによって実現される。マイクロフィッシュの付録Ａの実施形態では、式ユニットは「ｅｘｅ＿ｅｖａｌｕａｔｅ＿ｅｘｐｒ」ルーチンによって実現される。式ユニットについては、論理流れ図２４００（第２４図）として詳細に示す。
式の処理は、ｎｕｌｌ式判断２４０２（以下「判断２４０２」という）から始まる。判断２４０２は、入力式がｎｕｌｌ式と等しいかどうかを判定する。入力式がｎｕｌｌ式と等しいときは、いかなるアクションも不要であり、論理流れ図２４００による処理、したがって、式ユニットは終了する。そうではない場合、入力式がｎｕｌｌ式と等しくないときは、処理は現行コンテキスト保管アクション２４０４（以下「アクション２４０４」という）に移行する。アクション２４０４は、現行式２１１４の値を保管する。処理は、入力式を表す現行構文解析ツリー構造３０４内のノードを指すポインタを現行式２１１４に格納する新コンテキスト設定アクション２４０６（以下「アクション２４０６」という）に移行する。古いコンテキスト情報が保管され、新しいコンテキストが設定された後、処理は値判断２４０８（以下「判断２４０８」という）に移行する。
判断２４０８は、入力式が値であるかどうかを判定する。構文解析ツリーに関する前述の説明に戻ると、値は構文解析ツリー内のリーフノードである。一実施形態の値は、定数、変数、可変アドレス、またはルーチン・アドレスにすることができる。入力式が値である場合、処理は値探索アクション２４１０（以下「アクション２４１０」という）に移行し、そうではない場合、処理は演算判断２４２２（以下「判断２４２２」という）に移行する。
アクション２４１０は、入力式の値を決定するものである。構文解析ツリー構造３０４は各値ごとに固有の宣言ノードを有する。宣言ノードは、そのタイプやその内容など、値に関する情報を有する。アクション２４１０は、対応する宣言ノードを指すポインタを入力式を表すノードから取り出す。また、宣言ノードを指すポインタは、本明細書ではｅｘｔｅｒｎａｌ＿ｉｄともいう。これは、記号テーブル内の記号を探索するために使用するｅｘｔｅｒｎａｌ＿ｉｄである。値の内容の判定は、参照した宣言ノードによって行われる。参照した宣言ノードが値の内容を含まない場合、その値は「未知」としてフラグが付けられる。処理は、アクション２４１０から記号テーブル内検出判断２４１２（以下「判断２４１２」という）に移行する。
判断２４１２は、値が記号テーブルに格納されているかどうかを判定するものである。判断２４１２は、アクション２４１０で検出したｅｘｔｅｒｎａｌ＿ｉｄと、記号テーブル項目内の構文解析ツリー・ポインタ１３０２とを比較する。一致が検出された場合、その値は記号テーブル内にあり、処理はコンテキスト復元アクション２４２８（以下「アクション２４２８」という）に移行する。その値が記号テーブル内で検出されない場合、処理はメモリ作成アクション２４１４（以下「アクション２４１４」という）に移行する。
アクション２４１４は、現行式用に（すなわち、値用に）モデル化メモリをレイアウトするものである。アクション２４１４は、現行関数の戻り値用にモデル化メモリをレイアウトする前述のアクション１２０６と同様のものである。まず、アクション２４１４は、現行式を表すために必要なメモリの量を決定する。次に、アクション２４１４は、メモリ作成ユニット１５００を呼び出して、現行式を表すために必要な量のメモリをモデル化する。次にアクション２４１４は、（参照した宣言ノードで検出された）現行式の内容を新たにモデル化したメモリに格納する。現行式が変数である場合、アクション２４１４は作成したばかりの現行式位置を指すポインタをレイアウトする。アクション２４１４は、メモリ作成ユニット１５００を呼び出して、モデル化メモリのポインタ・サイズの区画を作成する。アクション２４１４は、現行式の位置の符号化アドレスを現行式を指すポインタ用の位置に格納する。処理はアクション２４１４から非ゼロ定数判断２４１６（以下「判断２４１６」という）に移行する。
判断２４１６は、現行式が非ゼロ定数であるかどうかを判定するものである。現行式が非ゼロ定数である場合、処理はアクション２４２８に移行し、そうではない場合、処理は記号テーブルへの追加アクション２４１８（以下「アクション２４１８」という）に移行する。アクション２４１８は、現行式を表すための記号テーブル項目１３００を作成し、新たに作成した記号テーブル項目１３００を記号テーブルに格納する。ゼロは記号テーブル内に配置される唯一の定数である。ゼロは、定数ゼロを使用するたびに何度もメモリをモデル化するのを回避するために最適化として記号テーブル内に配置される。処理はアクション２４１８からスタティックおよびグローバル変数のリスト保守アクション２４２０（以下「アクション２４２０」という）に移行する。
アクション２４２０は、自動モデル化のために、グローバル変数のリストとスタティック変数のリストを保守するものである。変数タイプ情報は現行式に対応する宣言ノードに記録されている。本発明の一実施形態では、変数は、グローバル、スタティック、またはローカルのいずれかのタイプにすることができる。現行式がグローバル変数である場合、アクション２４２０はグローバル変数リストを更新し、現行式がスタティック変数である場合、アクション２４２０はスタティック変数リストを更新することになる。処理はアクション２４２０からアクション２４２８に移行する。
入力式が値ではない場合、演算判断２４２２（以下「判断２４２２」という）は、現行式が演算であるかどうかを判定することになる。現行式が演算である場合、処理は演算処理アクション２４２４（以下「アクション２４２４」という）に移行する。アクション２４２４については以下に詳述する。現行式が演算ではない場合、処理は非評価ケース・アクション２４２６（以下「アクション２４２６」という）に移行する。アクション２４２６は、現行式を識別できない場合に適切なエラー・コードを発行する。現行式が分析エンジン３０８によってサポートされていない場合、いかなるアクションも行われない。たとえば、第２４図の実施形態では、「ｎｅｗ」と「ｄｅｌｅｔｅ」というＣ＋＋式はサポートされていない。処理はアクション２４２６からアクション２４２８に移行する。
アクション２４２８は、アクション２４０４で保管した値を現行式２１１４に復元する。次に、論理流れ図２４００による処理、したがって、式ユニットは終了する。終了すると、式ユニットは開始サイト制御に制御を移転する。
演算を処理するアクション２４２４については、論理流れ図２５００（第２５ａ図、第２５ｂ図）に示す。アクション２４２４は、どのタイプの演算を現行式が表しているかを判定し、適切な処理を実行する。演算式は、演算子と１つまたは複数のオペランドから構成される。オペランドも式である。処理は、現行式が関数呼出しを表すかどうかを判定する関数呼出し判断２５０２（以下「判断２５０２」という）から始まる。現行式が関数呼出しである場合、処理は、呼び出した関数をエミュレートする関数エミュレート・アクション２５０４（以下「アクション２５０４」という）に移行し、そうではない場合、処理は短絡演算判断２５０６（以下「判断２５０６」という）に移行する。
アクション２５０４は、その対応モデル１１８を実行することによって関数をエミュレートする。モデル１１８を実行すると、アクション２５０４は、対応する関数がメモリ・モデルに対してどのような影響を及ぼすか（関数の外部効果）を判定することができる。実行すべき関数が欠落モデルによって表される場合、アクション２５０４は、関数呼出しが正常に完了すると想定するだけである。付録Ｆには、アクション２５０４を実現するために使用する一実施形態の擬似コードが提示されている。アクション２５０４が完了すると、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。
判断２５０６は、現行式が短絡演算であるかどうかをチェックする。短絡演算子である論理積（＆＆）および論理和（｜｜）はこのように呼ばれる。というのは、（おそらくすべてのオペランドが評価される前に）演算の真理値が決定されると、ただちに演算の評価が停止するからである。現行式が短絡演算である場合、処理はＬＨＳ式評価アクション２５０８（以下「アクション２５０８」という）に移行する。アクション２５０８は、プロセス制御を式ユニット（アクション２４０２）に移転することにより、演算の左辺式（すなわち、左辺オペランド）を評価する。左辺式を評価した後、処理は、入力式の真理値が決定されたかどうかを判断する真理値決定判断２５１０（以下「判断２５１０」という）に移行する。入力式が論理積であって左辺式が偽と評価されるか、または入力式が論理和であって左辺式が真と評価された場合、入力式の真理値が決定され、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。そうではない場合、処理は、処理を式ユニット（アクション２４０２）に移行することにより現行式の右辺（すなわち、右辺オペランド）を評価するＲＨＳ式評価アクション２５１２（以下「アクション２５１２」という）に移行する。右辺式が評価された後、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。本発明の一実施形態では、アクション２４２４の処理はルーチンによって実行される。マイクロフィッシュの付録Ａの実施形態では、「ｅｘｅ＿ｅｖａｌｕａｔｅ＿ｏｐｅｒａｔｉｏｎ」ルーチンがアクション２４２４の処理を実行する。
現行式が短絡演算ではない場合、処理は、現行式が３項演算子「？：」であるかどうかを判定する疑問符演算判断２５１４（以下「判断２５１４」という）に移行する。現行式が疑問符演算である場合、処理は、疑問符演算のテスト式を評価するテスト式評価アクション２５１６（以下「アクション２５１６」という）に移行する。テスト式は、式ユニットを呼び出すことによって評価される。テスト式が評価された後、処理は、テスト式の真理値を検査するテスト式判断２５１８（以下「判断２５１８」という）に移行する。テスト式が真と評価された場合、処理は、「真」というテスト式結果に対応する式を評価する「真」式評価アクション２５２０（以下「アクション２５２０」という）に移行する。そうではない場合、処理は、真ではないテスト式結果に対応する式を評価する「偽」式評価アクション２５２２（以下「アクション２５２２」という）に移行する。アクション２５２０またはアクション２５２２の後、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。
現行式が疑問符演算ではない場合、処理は、現行式がカンマ演算であるかどうかを判定するカンマ演算判断２５２４（以下「判断２５２４」という）に移行する。現行式がカンマ演算である場合、処理はＬＨＳ評価（戻り値なし）アクション２５２６（以下「アクション２５２６」という）に移行する。アクション２５２６は、カンマ演算の左辺式を評価する。アクション２５２６は、左辺式に関して返された値を必要としないので、空ポインタを式ユニットに渡す。左辺式の評価後、処理は、カンマ演算の右辺式を評価するＲＨＳ評価（戻り値）アクション２５２８（以下「アクション２５２８」という）に移行する。アクション２５２８は戻り値を必要とするので、式の結果用の位置を指すポインタによって式ユニットを呼び出す。アクション２５２８の後、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。
現行式がカンマ演算ではない場合、処理は、現行式がビット・フィールドまたはフィールド演算であるかどうかを判定するビット・フィールドおよびフィールド演算判断２５３０（以下「判断２５３０」という）に移行する。現行式がビット・フィールドまたはフィールド演算である場合、演算子が構造内のフィールドを参照することを意味し、処理はｌｈｓ式評価アクション２５４０（以下「アクション２５４０」という）に移行する。
アクション２５４０は、式評価ユニットを呼び出すことにより、左辺オペランド（すなわち、ｌｈｓ式）を評価する。左辺式は、ビット・フィールドまたはフィールド演算が参照する構造を指すポインタである。左辺式が評価された後、処理制御は、値必要判断２４５２（以下「判断２５４２」という）に移転する。
判断２５４２は、ビット・フィールドまたはフィールド演算がその構造から値を取り出すかどうかを判定する。演算が値を必要とする場合、処理はメモリ作成アクション２５４４（以下「アクション２５４４」という）に移行し、そうではない場合、処理制御はｒｈｓ  ａｒｇとしてのオフセットの使用アクション２５４６（以下「アクション２５４６」という）に移転する。アクション２５４４は、演算が参照する値用のメモリを作成するものである。アクション２５４４は、メモリ作成ユニット１５００を呼び出して、構造参照の結果得られる値を保持するために十分な大きさのモデル化メモリの区画を作成する。必要なモデル化メモリが作成された後、処理はアクション２５４６に移行する。
アクション２５４６は、右辺オペランドに対応する引数情報ブロック２６００に、位置情報ではなくフィールド・オフセット情報を記入することにより、演算ユニットを呼び出すための準備を行う。引数情報ブロック２６００については以下に詳述する。処理制御は演算評価アクション２５３８に移転する。
現行式がビット・フィールドまたはフィールド演算ではない場合、処理はＬＨＳ式評価アクション２５３２（以下「アクション２５３２」という）に移行する。処理制御がアクション２５３２に到達した場合、現行式が特殊ケースの処理を必要としないことが分かっており、「通常」演算処理が始まる。アクション２５３２は、現行式の左辺を評価するものである。すべての演算は少なくとも１つの左辺オペランドを有することになる。左辺式が評価された後、処理は、現行式が２項演算であるかどうかを判定する２項演算判断２５３４（以下「判断２５３４」という）に移行する。現行式が２項演算である場合、処理は、現行式の右辺を評価するＲＨＳ式評価アクション２５３６（以下「アクション２５３６」という）に移行する。右辺式が評価された後または現行式が単項演算であると判定された後、処理は演算評価アクション２５３８（以下「アクション２５３８」という）に移行する。
アクション２５３８は、評価すべき演算を表す演算子と、引数情報ブロック２６００（第２６図）内にパッケージ化された演算子の各オペランドとを指定して演算ユニットを呼び出すことにより、演算を評価するものである。前述のように、現行式がビット・フィールドまたはフィールド演算である場合、右辺オペランドに対応する引数情報ブロック２６００は実際には、モデル化メモリ位置とは対照的に、構造内へのオフセットを表す。引数情報ブロック２６００は、「位置ポインタ」２６０２と、「サイズ」２６０４と、「ブール」２６０６と、「ポイントからサイズ」２６０８と、「ポイント間からサイズ」２６１０と、「ビット・フィールド・フラグ」２６１２と、「ビット・オフセット」２６１４と、「ビット・サイズ」２６１６と、「印字式」２６１８というフィールドを含む。
フィールド「位置ポインタ」２６０２は、現在の引数ブロック２６００に対応する引数のモデル化メモリ用の符号化ポインタに設定される。各オペランドは、別々の引数ブロック２６００によって記述される。フィールド「サイズ」２６０４は、フィールド「位置ポインタ」２６０２が指し示すメモリのサイズに設定される。一部の演算はブール値を返し、返されたブール値はフィールド「ブール」２６０６に格納される。フィールド「ポイントからサイズ」２６０８は、フィールド「位置ポインタ」２６０２が指し示すモデル化メモリ位置にある値が指し示すもののサイズを保持する。フィールド「ポイント間からサイズ」２６１０は、フィールド「位置ポインタ」２６０２が参照する値が指し示す位置にある値が指し示すもののサイズを保持する。フラグ「ビット・フィールド・フラグ」２６１２は、フィールド「位置ポインタ」２６０２がビット・フィールドであるときにオンになる。フィールド「ビット・オフセット」２６１４は、ビット・フィールドの開始点を示す。フィールド「ビット・サイズ」２６１６は、ビット・フィールドのビット単位のサイズを保持する。フィールド「印字式」２６１８は、引数情報ブロック２６００に記述された値を含む式を印字可能なフォーマットで格納する。
演算ユニットから戻った後、論理流れ図２５００による処理、したがって、アクション２４２４は終了する。終了すると、アクション２４２４はアクション２４２８（第２４図）に処理を移転する。
演算ユニットについては論理流れ図２７００（第２７図）に示す。一般に、演算ユニットは組込みモデルを実行して、演算の結果を判定する。組込みモデルはモデル１１８と同様のものである。モデル制約と同様に、実行すべき演算について真になるべきものが真になっていることを確認するテストが行われる。次に、モデル結果と同様に、演算を実行したあとで真であることが確認されるものを記述する結果が生成される。演算ユニットはいつでも結果の位置を返す。返された位置が空になることもありうる。演算ユニットの処理はテスト選択アクション２７０２（以下「アクション２７０２」という）から始まる。本発明の一実施形態では、演算ユニットの処理はルーチンによって行われる。マイクロフィッシュの付録Ａの実施形態では、「ｉｎｓ＿ｅｖａｌｕａｔｅ＿ｏｐｅｒａｔｉｏｎ」というルーチンが演算ユニットの処理を実行する。
アクション２７０２は、評価中の演算について実行すべきテストを選択する。実行するために使用可能なテストとしては、「ｃｏｍｐａｒａｂｌｅ」、「ｖａｌｉｄ＿ｐｏｉｎｔｅｒ」、「ｉｎｉｔｉａｌｉｚｅｄ」、「ｎｏｎ＿ｚｅｒｏ」がある。「ｃｏｍｐａｒａｂｌｅ」テストは、２つのポインタが同じ格納値セットを指し示すかどうかを判定する。分析エンジン３０８はメモリを正確に複製するわけではないので、２つのポインタは、モデル化メモリの同じ区画を指し示す場合のみ、比較することができる。「ｖａｌｉｄ＿ｐｏｉｎｔｅｒ」テストは、その位置が有効なポインタ、すなわち、モデル化メモリのうちの現在使用中の区画を指すポインタを含むかどうかを判定する。「ｉｎｉｔｉａｌｉｚｅｄ」テストは、所与の位置に値があるかどうかを判定する。「ｉｎｉｔｉａｌｉｚｅｄ」テストは、その位置に対応する格納値ブロック１８００を調べ、フラグ「初期設定済みフラグ」１８０８をチェックして、その値が初期設定されているかどうかを判定する。「ｎｏｎ＿ｚｅｒｏ」テストは、ある位置が定数ゼロ以外の値を含むかどうかを判定する。このテストは、ゼロに等しい除数に関するスクリーニングのために使用する。各演算ごとに、適用するテストと、そのテストが適用されるオペランドを付録Ｃに列挙する。
適切なテストが選択された後、処理はフィールド演算子判断２７０４（以下「判断２７０４」という）に移行する。判断２７０４は、分析中の演算子がビット・フィールドまたはフィールド演算子であるかどうかを判定する。分析中の演算子がフィールド演算子である場合、処理はオフセット・メモリ作成アクション２７０６（以下「アクション２７０６」という）に移行し、そうではない場合、処理は単項演算子判断２７１８（以下「判断２７１８」という）に移行する。
アクション２７０６は、右辺引数に対応する引数情報ブロック２６００に格納されたフィールド構造内のオフセットを保持するためにモデル化メモリの区画を作成する。このオフセットは、新たに作成したモデル化メモリ位置に格納される。処理はテスト実行アクション２７０８（以下「アクション２７０８」という）に移行する。
アクション２７０８は、アクション２７０２で選択したテストを実行する。実行すべき各テストごとに、アクション２７０８は、分析中の演算子と、テスト中のオペランドに対応する引数情報ブロック２６００と、テストが成功したかどうかを報告する条件変数とを指定してｖｉｍ基本テスト・ユニットを呼び出す。ｖｉｍ基本テスト・ユニットは、指示したテストを実行するためにメモリ・モデルに問い合わせる。ｖｉｍ基本テスト・ユニットについては以下に詳述する。選択したすべてのテストが実行された後、処理は加算演算子適用アクション２７１０（以下「アクション２７１０」という）に移行する。
アクション２７１０は、分析中の演算子と、左辺オペランド（すなわち、構造の位置）に対応する引数情報ブロック２６００と、右辺オペランド（すなわち、構造内へのオフセットの位置）に対応する引数情報ブロック２６００と、結果位置を指すポインタと、演算によって１が生成される場合に真理値を保持するための条件変数とを指定してｖｉｍ基本評価ユニットを呼び出すことにより、ポインタ加算演算子を評価する。ｖｉｍ基本評価ユニットは、指示した演算の結果を達成するようにメモリ・モデルを操作する。ｖｉｍ基本評価ユニットについては以下に詳述する。ポインタ加算演算子の結果は、構造内の参照フィールドを指すポインタである。加算演算を評価した後、処理はフィールド値必要判断２７１２（以下「判断２７１２」という）に移行する。
判断２７１２は、フィールド演算子がフィールドの値を必要とするかどうかを判定する。フィールド演算子は、構造内の参照フィールドの内容を返すときに値を必要とする。フィールド値が必要である場合、処理はテスト実行アクション２７１４（以下「アクション２７１４」という）に移行し、そうではない場合、論理流れ図２７００による処理、したがって、演算ユニットは終了する。
アクション２７１４は、アクション２７０８と同様に、アクション２７０２で選択したテストを実行する。テストが実行された後、処理はデリファレンス演算子適用アクション２７１６（以下「アクション２７１６」という）に移行する。アクション２７１６は、分析中の演算子と、左辺オペランド（すなわち、構造内の参照フィールドを指すポインタ）に対応する引数情報ブロック２６００と、結果位置を指すポインタと、演算によって１が生成される場合に真理値を保持するための条件変数とを指定してｖｉｍ基本評価ユニットを呼び出すことにより、ポインタ・デリファレンス演算子を評価する。ｖｉｍ基本評価ユニットは、指示した演算の結果を達成するようにメモリ・モデルを操作する。ポインタ・デリファレンス演算は、構造内の参照フィールドの内容を返す。ポインタ・デリファレンス演算子を評価した後、論理流れ図２７００による処理、したがって、演算ユニットは終了する。
判断２７１８は、分析中の演算子が単項演算子であるかどうかを判定する。分析中の演算子が単項演算子である場合、処理はテスト実行アクション２７２０（以下「アクション２７２０」という）に移行し、そうではない場合、処理は２項演算子判断２７２４（以下「判断２７２４」という）に至る。アクション２７２０は、アクション２７０８と同様に、アクション２７０２で選択したテストを実行する。選択したすべてのテストが実行された後、処理は単項演算子適用アクション２７２２（以下「アクション２７２２」という）に移行する。アクション２７２２は、分析中の演算子と、左辺オペランドに対応する引数情報ブロック２６００と、結果位置を指すポインタと、演算によって１が生成される場合に真理値を保持するための条件変数とを指定してｖｉｍ基本評価ユニットを呼び出すことにより、単項演算子を評価する。単項演算を評価した後、処理は未決定関係判断２７３０（以下「判断２７３０」という）に移行する。
演算子が単項演算子ではない場合、処理は、演算子が２項演算子であるかどうかを判定する判断２７２４に移行する。演算子が２項演算子である場合、処理はテスト実行アクション２７２６（以下「アクション２７２６」という）に移行し、そうではない場合、処理は判断２７３０に至る。アクション２７２６は、アクション２７２０と同様に、アクション２７０２で選択したテストを実行する。テストが実行された後、処理は２項演算子適用アクション２７２８（以下「アクション２７２８」という）に移行する。
アクション２７２８は、分析中の演算子と、左辺オペランドに対応する引数情報ブロック２６００と、右辺オペランドに対応する引数情報ブロック２６００と、結果位置を指すポインタと、演算によって１が生成される場合に真理値を保持するための条件変数とを指定してｖｉｍ基本評価ユニットを呼び出すことにより、２項演算を評価する。２項演算を評価した後、処理は判断２７３０に移行する。
判断２７３０は、評価した演算が、「不明」値であると評価された関係演算であったかどうかを確認するためのチェックを行う。モデル化メモリが実メモリの正確な複製ではない場合の結果の１つは、モデル化メモリが３値真理論理を使用することである。モデル化メモリ内の真理値は、「真」、「偽」、「不明」のいずれかになる。「不明」条件は、真のメモリに関する知識が不完全であることによる。演算の結果、「不明」条件が発生した場合、モデル化メモリの３値真理論理を２値真理論理に変換しなければならない。判断２７３０が真になる場合、処理は条件選択アクション２７３２（以下「アクション２７３２」という）に移行する。アクション２７３２は、ＣＰＨ条件選択ユニットを呼び出すことによって条件を選択する。ＣＰＨ条件選択ユニットについては以下に詳述する。選択が行われると、アクション２７３２は、位置に対応する格納値ブロック１８００でフラグ「想定値フラグ」１８１０をオン（真）に設定する。処理は情報想定アクション２７３４（以下「アクション２７３４」という）に移行する。
アクション２７３２で選択が行われた場合、その選択の含意を示すためにモデル化メモリを必ず更新しなければならない。式の結果を選択することは、その式で使用するオペランドに関する派生効果を有する。たとえば、以下のコード・サンプルを検討する。
0004633203.tif 000006
変数ｉに関する情報が一切不明である場合、ゼロと同等であるｉを評価すると、「不明」値が返されることになる。変数ｉと定数ゼロとを比較するための情報がまったくないので、ｖｉｍ基本評価ユニットによって「不明」という値が返される。ｉがゼロと同等であると想定するという選択が行われた場合、コード・パスに沿って今後のステートメントで変数ｉを一貫して使用するためには、ｉがゼロと等しいことを反映するようにメモリを更新しなければならない。アクション２７３４は、モデル化メモリを適切に更新するためにｖｉｍ想定ユニットを呼び出す。ｖｉｍ想定ユニットについては以下に詳述する。ｖｉｍ想定ユニットから戻ると、論理流れ図２７００による処理、したがって、演算ユニットは終了する。終了すると、処理制御は開始サイト制御に返される。
選択点を解決するための条件の選択は、ＣＰＨ条件選択ユニットによって行われる。ＣＰＨ条件選択ユニットについては論理流れ図３３００（第３３図）に示す。処理は、選択実行判断３３０２（以下「判断３３０２」という）から始まる。判断３３０２は、実行すべき選択がアクション１１０８で構築したパスの一部に対応するかどうかを判定する。実行すべき選択がアクション１１０８で決定したパス上の選択点によってすでに表されている場合、処理は選択アクション３３０４（以下「アクション３３０４」という）に移行する。アクション３３０４はアクション１１０８で構築したパスが指示する選択を行い、論理流れ図３３００による処理、したがって、ＣＰＨ条件選択ユニットは終了する。
判断３３０２が偽を返す場合、いかなる選択も前もって決定されていないので、処理はランダム選択アクション３３０６（以下「アクション３３０６」という）に移行する。解決するためにＣＰＨ条件選択ユニットが呼び出された未解決の選択点が選択点ノードに対応することに留意されたい。また、未解決の選択点に関して可能な解決は、その選択点ノードから出る選択エッジに対応する。アクション３３０６は、未調査の選択エッジ間でランダム選択を行うことによって、結果（選択）を抜き取る。選択が行われた後、処理はＣＰＨツリー更新アクション３３０８（以下「アクション３３０８」という）に移行する。
アクション３３０８は、選択点ノードで選択したエッジ選択にマークを付けるものである。この選択点ノードがすでにＣＰＨツリー上にあるものではない場合、アクション３３０８はこれをツリーに挿入する。ＣＰＨツリーが更新された後、論理流れ図３３００による処理、したがって、ＣＰＨ条件選択ユニットは終了する。終了すると、処理制御は開始サイト制御に戻る。本発明の一実施形態では、ＣＰＨ条件選択ユニットはルーチンによって行われる。マイクロフィッシュの付録Ａの実施形態では、「ｃｐｈ＿ｃｈｏｏｓｅ＿ｃｏｎｄｉｔｉｏｎ」というルーチンがＣＰＨ条件選択ユニットの処理を実行する。
ｉｆ−ｅｌｓｅユニットは、ｉｆ−ｅｌｓｅステートメントを処理するものである。ｉｆ−ｅｌｓｅユニットについては論理流れ図２８００（第２８図）として詳細に示す。ｉｆ−ｅｌｓｅユニットの処理は、テスト式評価アクション２８０２（以下「アクション２８０２」という）から始まる。アクション２８０２はｉｆ−ｅｌｓｅステートメントのテスト式を評価する。前述のように、式ユニット（アクション２４０２）を呼び出すことにより、式を評価する。テスト式が評価された後、処理は、テスト式の結果を検査するテスト式結果判断２８０４（以下「判断２８０４」という）に移行する。テスト式が真であると評価された場合、処理は、ｉｆ式を評価する「ｉｆ」式評価アクション２８０６（以下「アクション２８０６」という）に移行する。そうではない場合、処理は、偽式を評価する「偽」式評価アクション２８０８（以下「アクション２８０８」という）に移行する。アクション２８０６または２８０８後に、論理流れ図２８００の処理、したがって、ｉｆ−ｅｌｓｅユニットは終了する。終了すると、ｉｆ−ｅｌｓｅユニットは開始サイト制御に制御を移転する。
ｗｈｉｌｅループ、ｄｏ  ｗｈｉｌｅループ、ｆｏｒの各ユニットは、いずれもループ実行ユニットを呼び出して、それぞれに対応するステートメントの処理を実行する。３つのユニット間の唯一の違いは、ｆｏｒユニットはループ実行ユニットを呼び出す前に初期設定ステートメントを評価することである。ｆｏｒユニットは、処理制御をアクション１２０８に移転することにより、初期設定ステートメントを評価する。ループ実行ユニットについては論理流れ図２９００（第２９図）として詳細に示す。本発明の一実施形態では、ループ実行ユニットはルーチンによって行われる。マイクロフィッシュの付録Ａの実施形態では、「ｅｘｅ＿ｌｏｏｐ」というルーチンがループ実行ユニットの処理を実行する。
ループ実行ユニットは、ループ・ステートメントを指し示すために実行コンテキスト・ブロック２１００のフィールド「現行ステートメント」２１１０を更新するステートメント・コンテキスト設定アクション２９０２から処理を始める。処理は、現行ステートメントがｆｏｒまたはｗｈｉｌｅループであるかどうかを判定するｆｏｒまたはｗｈｉｌｅループ判断２９０４に移行する。現行ステートメントがｆｏｒまたはｗｈｉｌｅループである場合、処理は、条件偽またはループ終了判断２９０６（以下「判断２９０６」という）に移行する。そうではない場合、処理はループ未終了判断２９１０（以下「判断２９１０」という）に至る。
判断２９０６は、式評価ユニットを呼び出すことにより、テスト条件式を評価する。判断２９０６は、条件が偽であるかまたはループが終了したかどうかを判定する。基本的にこれは、ループの本体より前にテストが評価されることを意味する。ループ条件が偽であるかまたはループが終了した場合、処理は、ループ終了フラグをオンにして、ループが完了したことを記憶するループ完了記憶アクション２９０８に移行する。そうではない場合、処理は判断２９１０に移行する。
判断２９１０は、ループ終了フラグに問い合わせて、ループが完了したかどうかを判定する。ループが完了していない場合、処理はアクション２９１２に移行する。そうではない場合、処理はｄｏ  ｗｈｉｌｅループ判断２９１８（以下「判断２９１８」という）に移行する。アクション２９１２は、ループ本体内のすべてのステートメントを実行する。各ステートメントは、アクション１２０８を呼び出すことによって実行される。ループ本体内の各ステートメントが実行されると、処理は、現行ステートメントがｆｏｒループであるかどうかを判定するｆｏｒループ判断２９１４に移行する。現行ステートメントがｆｏｒループである場合、処理は、式ユニットを呼び出すことにより増分式を評価するアクション２９１６に移行する。増分式が評価された後、または現行ステートメントがｆｏｒループではない場合、処理は判断２９１８に移行する。
判断２９１８は、現行ループがｄｏ  ｗｈｉｌｅループであるかどうかを判定する。現行ループがｄｏ  ｗｈｉｌｅループである場合、処理は、式ユニットを呼び出すことによりループ・テスト式を評価するテスト式評価アクション２９２０に移行する。ｄｏ  ｗｈｉｌｅループの場合、テストはループの本体のあとで評価される。最終テスト式が評価された後、または現行ループがｄｏ  ｗｈｉｌｅループではない場合、論理流れ図２９００による処理、したがって、ループ実行ユニットは終了する。ループ実行ユニットはループ本体の１回の実行だけをシミュレートする。終了すると、ループ実行ユニットは開始サイト制御に制御を返す。
ｓｗｉｔｃｈユニットはｓｗｉｔｃｈステートメントを処理する。ｓｗｉｔｃｈユニットについては論理流れ図３０００（第３０ａ図、第３０ｂ図）に示す。ｓｗｉｔｃｈユニットの処理は、ｓｗｉｔｃｈテスト式を評価するテスト式評価アクション３００２から始まる。ｓｗｉｔｃｈテスト式は、式ユニットへの呼出しにより評価される。制御は、他のｃａｓｅラベルを検査しなければならないかどうか、ならびにチェックすべきｃａｓｅラベルが残っているかどうかを判定するチェックすべきｃａｓｅラベル判断３００４に移転する。依然としてｃａｓｅラベルを検査する必要性があり、依然としてチェックすべきものが複数ある場合、処理は宣言ノード検索アクション３００６（以下「アクション３００６」という）に移行し、そうではない場合、処理はｃａｓｅ選択判断３０２８（以下「判断３０２８」という）に移行する。
アクション３００６は、処理すべき次のｃａｓｅラベル用の宣言ノードを検索する。処理は、アクション３００６から、ｃａｓｅラベルが記号テーブル内にあるかどうかを判定する記号テーブル内ラベル判断３００８に移行する。ｃａｓｅラベルが記号テーブル内にある場合、処理はラベル集合構築アクション３０１２（以下「アクション３０１２」という）に移行する。そうではない場合、処理は、そのｃａｓｅラベルを記号テーブルに追加する記号テーブルへのラベル追加アクション３０１０（以下「アクション３０１０」という）に移行する。
アクション３０１０は、そのｃａｓｅラベルを表すための記号テーブル項目１３００を作成する。新たに作成した記号テーブル項目１３００は記号テーブルに格納される。処理は、アクション３０１０からアクション３０１２に移行する。アクション３０１２は、そのｃａｓｅラベルをラベル集合に格納し、検討したすべてのｃａｓｅラベルの集合を構築する。処理は、アクション３０１２から、ｃａｓｅ内の第１のステートメントを指すポインタの集合を構築するステートメント集合構築アクション３０１４に移行する。検討した各ｃａｓｅラベルごとに１つずつのポインタが存在する。ステートメント集合が更新された後、処理は式ｃａｓｅラベル同等判断３０１６（以下「判断３０１６」という）に移行する。
判断３０１６は、ｓｗｉｃｈテスト式の結果とｃａｓｅラベルとを突き合わせる。ｓｗｉｔｃｈテスト式の結果がｃａｓｅラベルと等しい場合、処理は現在のｃａｓｅ選択アクション３０１８（以下「アクション３０１８」という）に移行する。アクション３０１８は、現在のｃａｓｅラベルに対応するステートメントを実行すべきであることを示す。処理は、チェックすべきｃａｓｅラベルがこれ以上ないことを示すためにフラグを設定する調査停止記憶アクション３０２０（以下「アクション３０２０」という）に移行する。処理はアクション３０２０から判断３００４に移行する。
ｓｗｉｔｃｈテスト式の結果が現在のｃａｓｅラベルと等しくなかった場合、処理は、突合せが偽を返したかどうかを判定する突合せ結果偽判断３０２２に移行する。突合せが偽を返した場合、処理は、偽の突合せの数をカウントする偽ｃａｓｅカウント・アクション３０２４（以下「アクション３０２４」という）に移行する。ｓｗｉｔｃｈテスト式の結果とｃａｓｅラベルが等しいことを判定できなかった場合、処理は、「不明」ｃａｓｅ集合構築アクション３０２６（以下「アクション３０２６」という）に移行する。アクション３０２６は、判断３０１６が結果を判定できなかったすべてのケースに対応するｃａｓｅラベルの集合に現在のｃａｓｅラベルを追加する。処理は、アクション３０２４およびアクション３０２６から判断３００４に移行する。
ｃａｓｅ選択判断３０２８は、ｃａｓｅが選択されたかどうかを判定する。ｃａｓｅが選択された場合、処理は、次のｂｒｅａｋステートメントに到達するまで選択したｃａｓｅ内のステートメントを実行する次のｂｒｅａｋまでステートメントを実行するアクション３０３０に移行する。アクション１２０８を呼び出すことにより、ステートメントを実行する。ｃａｓｅ内のすべてのステートメントが実行されると、論理流れ図３０００による処理、したがって、ｓｗｉｔｃｈユニットは終了する。
ｃａｓｅがまだ選択されていない場合、処理は、偽ｃａｓｅの数がｓｗｉｔｃｈステートメント内のｃａｓｅの数に等しいかどうかを判定する偽カウントｃａｓｅ数同等判断３０３２に移行する。偽ｃａｓｅの数がｃａｓｅの数に等しい場合、いずれのｃａｓｅラベルもｓｗｉｔｃｈテスト式結果と一致しないことを意味し、処理はデフォルトｃａｓｅ内のステートメントを実行するデフォルトｃａｓｅ実行アクション３０３４（以下「アクション３０３４」という）に移行する。アクション１２０８を呼び出すことにより、ステートメントを実行する。アクション３０３４が完了すると、論理流れ図３０００による処理、したがって、ｓｗｉｔｃｈユニットは終了する。偽ｃａｓｅのカウントがｓｗｉｔｃｈステートメント内のｃａｓｅの数に等しくない場合、処理は不明ｃａｓｅ判断３０３６（以下「判断３０３６」という）に至る。
判断３０３６は、「不明」ｃａｓｅの集合内にラベルがあるかどうかを判定する。「不明」ｃａｓｅ内にラベルがある場合、処理は不明ｃａｓｅとデフォルトｃａｓｅの選択アクション３０３８（以下「アクション３０３８」という）に移行する。そうではない場合、ｓｗｉｔｃｈユニット内の処理は終了する。
アクション３０３８は、「不明」ｃａｓｅとデフォルトｃａｓｅとから実行すべきｃａｓｅを選択する。アクション３０３８は、ＣＰＨ条件選択ユニット（第３３図）を呼び出すことにより、どのｃａｓｅを選択するかを判定する。ＣＰＨ条件選択ユニットについては以下に詳述する。処理は、アクション３０３８から、アクション３０３８で行った選択に基づいて情報を想定する情報想定アクション３０４０（以下「アクション３０４０」という）に移行する。アクション３０４０は、演算ユニットのアクション２７３４（第２７図）と同様のものである。アクション３０４０は、ｖｉｍ想定ユニットを呼び出して、アクション３０３８で行った選択に基づいてモデル化メモリを更新する。
処理は、アクション３０４０から、次のｂｒｅａｋステートメントが検出されるまで選択したｃａｓｅ内のステートメントを実行するｂｒｅａｋまでのステートメント実行アクション３０４２に移行する。ステートメントは、アクション１２０８への呼出しにより実行される。ステートメントが実行された後、論理流れ図３０００による処理、したがって、ｓｗｉｔｃｈユニットは終了する。終了すると、ｓｗｉｔｃｈユニットは開始サイト制御に処理制御を返す。
変数初期設定ユニットは、変数初期設定ステートメントを処理するものである。変数初期設定ユニットについては論理流れ図３１００（第３１図）として示す。変数初期設定ユニットの処理は、初期設定式を評価する初期設定評価アクション３１０２から始まる。初期設定式は、式ユニットを呼び出すことによって評価される。初期設定式が評価された後、処理は、代入された値を受け取る変数用の宣言ノードを突き止める、変数宣言ノード検出アクション３１０４（以下「アクション３１０４」という）に移行する。処理は、アクション３１０４から、演算ユニットを呼び出すことにより代入を評価する代入評価アクション３１０６に移行する。演算ユニットは代入演算子を指定して呼び出される。代入が評価された後、論理流れ図３１００による処理、したがって、変数初期設定ユニットは終了する。
ｒｅｔｕｒｎユニットはｒｅｔｕｒｎステートメントを処理するものである。ｒｅｔｕｒｎユニットについては論理流れ図３２００（第３２図）として示す。ｒｅｔｕｒｎユニットは、ｒｅｔｕｒｎステートメントが式を有するかどうかを判定するｒｅｔｕｒｎ式判断３２０２から処理を始める。ｒｅｔｕｒｎステートメントがｒｅｔｕｒｎ式を有していない場合、処理は式評価アクション３２０４（以下「アクション３２０４」という）に移行する。そうではない場合、ｒｅｔｕｒｎユニットは終了する。
アクション３２０４は、式ユニットを呼び出すことにより式を評価する。ｒｅｔｕｒｎ式が評価された後、処理は、記号テーブル内の戻り値を探索する記号テーブル内の戻り値探索アクション３２０６（以下「アクション３２０６」という）に移行する。アクション３２０６は、戻り値に対応する記号テーブル項目１３００からフィールド「記号位置」１３０６を検索する。処理は、ｒｅｔｕｒｎ記号へのｒｅｔｕｒｎ式の代入を評価する代入評価アクション３２０８（以下「アクション３２０８」という）に移行する。アクション３２０８は、変数初期設定ユニットのアクション３１０６（第３１図）と同様のものである。代入は、代入演算子を指定して演算ユニットを呼び出すことによって評価される。代入が評価された後、論理流れ図３２００による処理、したがって、ｒｅｔｕｒｎユニットは終了する。
ラベル・ユニットは、ステートメントを導入するラベルを処理するものである。ラベルとは、あとにコロン（「：」）が続く識別子である。「識別子」という用語は、Ｂｒｉａｎ  Ｗ．ＫｅｒｎｉｇｈａｎおよびＤｅｎｎｉｓ  Ｍ．ＲｉｔｃｈｉｅによるＴｈｅ  Ｃ  Ｐｒｏｇｒａｍｍｉｎｇ  Ｌａｎｇｕａｇｅ、１７９（Ｐｒｅｎｔｉｃｅ−Ｈａｌｌ、１９７８年）に定義されているように、ここで使用する。一実施形態のラベル・ユニットは、フロースルー処理を実行するだけであり、ラベル・ユニットは開始サイト制御に処理制御を移転する。
ｇｏｔｏユニットは、ｇｏｔｏステートメント内に指示されたステートメント（ｇｏｔｏ「ターゲット」ステートメント）に移行するように現行パスの制御の流れを方向付けるものである。ｇｏｔｏユニットは、前述のようにｇｏｔｏパラメータを真に設定する。ｇｏｔｏユニットは、ｇｏｔｏターゲット・ステートメントを表す現行構文解析ツリー構造３０４内のノードを指すポインタを検索し、そのポインタを処理制御とともにアクション１２０８に転送する。制御がｇｏｔｏユニットに戻ると、処理は終了し、ｇｏｔｏユニットは開始サイト制御に制御を移転する。本発明の一実施形態では、ｇｏｔｏユニットはルーチンによって実現される。マイクロフィッシュの付録Ａの実施形態では、ｇｏｔｏユニット２３は、「ｅｘｅ＿ｇｏｔｏ＿ｓｔａｔｅｍｅｎｔ」というルーチンによって実現される。
仮想イメージ・オブジェクト７０８
仮想イメージ・オブジェクト７０８は、メモリ・モデルを構築、更新、および検査する。仮想イメージ・オブジェクト７０８は、４つのユニット、すなわちメモリ作成ユニット１５００（前述）、活力（ｖｉｍ）プリミティブ試験ユニット、活力プリミティブ評価ユニット、および活力想定ユニットから構成される。仮想イメージ・オブジェクト７０８のこれら４つのユニットは、メモリ・モデルについての試験および操作を実行し、こうした試験および操作が活力プリミティブと呼ばれる。活力プリミティブは、メモリ・モデルの記憶された値に対して直接実行されるわけではなく、フェッチ値と呼ばれる記憶された値の検索したコピーに対して実行される。フェッチ値の使用は、値を操作する前にレジスタ中に置くコンピュータ・プログラムと類似している。活力プリミティブのある特定の使用についての情報は述語に集められる。述語は、後に自動モデル化に使用するためにログすることができる。活力プリミテイブ、フェッチ値、述語、プリミティブ評価ユニット、および想定ユニットについて、以下でさらに詳細に考察する。
本発明の１実施形態では、１８個の別個の活力プリミティブがある。活力プリミティブは、ｔｒｕｅ＿ａｓ＿ｃｏｎｄｉｔｉｏｎ、ｆａｌｓｅ＿ａｓ＿ｃｏｎｄｉｔｉｏｎ、ｉｎｉｔｉａｌｉｚｅｄ、ｖａｌｉｄ＿ｏｒ＿ｎｕｌｌ＿ｐｏｉｎｔｅｒ、ｖａｌｉｄ＿ｐｏｉｎｔｅｒ、ｉｎｖａｌｉｄ＿ｐｏｉｎｔｅｒ、ｖａｌｉｄ＿ｏｆｆｓｅｔ、ｃｏｍｐａｒａｂｌｅ、ｉｎｃｏｍｐａｒａｂｌｅ、ｆｒｅｅａｂｌｅ、ｆｒｅｅｄ＿ｍｅｍｏｒｙ、ｎｅｗ＿ｍｅｍｏｒｙ、ｎｏｎ＿ｚｅｒｏ、ｌｏｓｔ、ｉｎｔ＿ｔｏ＿ｆｌｏａｔ、ｆｌｏａｔ＿ｔｏ＿ｉｎｔ、ｓｔａｔｅ＿ｅｑ、およびｓｔａｔｅ＿ｎｅである。活力プリミティブ「ｔｒｕｅ＿ａｓ＿ｃｏｎｄｉｔｉｏｎ」は、指定された位置が「真」であると評価されるかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｆａｌｓｅ＿ａｓ＿ｃｏｎｄｉｔｉｏｎ」は、指定された位置が「真」以外の値であると評価されるかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｉｎｉｔｉａｌｉｚｅｄ」は、指定された位置が初期値を含むかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブ「ｖａｌｉｄ＿ｏｒ＿ｎｕｌｌ＿ｐｏｉｎｔｅｒ」は、指定された位置が、モデル化されたメモリの現在使用されている部分を指すポインタである有効ポインタ、または現在どこも指していない位置を指定するヌル・ポインタのいずれかを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｖａｌｉｄ＿ｐｏｉｎｔｅｒ」は、指定された位置が、有効ポインタ、すなわちモデル化されたメモリの現在使用されている部分を指すポインタを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｉｎｖａｌｉｄ＿ｐｏｉｎｔｅｒ」は、指定された位置が、モデル化されたメモリの現在使用されている部分を指すポインタを含まないかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブ「ｖａｌｉｄ＿ｏｆｆｓｅｔ」は、指定された位置が、識別された構造またはアレイ中への有効オフセットを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｃｏｍｐａｒａｂｌｅ」は、２つの位置が同じチャンク１７００を指すかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｉｎｃｏｍｐａｒａｂｌｅ」は、２つの位置が同じチャンク１７００を指さないかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｆｒｅｅａｂｌｅ」は、指定された位置が解放可能なメモリを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｆｒｅｅｄ＿ｍｅｍｏｒｙ」は、指定された位置を解放するよう活力ユニットに命令するものである。活力プリミティブ「ｎｅｗ＿ｍｅｍｏｒｙ」は、メモリ・モデル中で新しい位置を割り当てるよう活力ユニットに命令するものである。
活力プリミティブ「ｎｏｎ＿ｚｅｒｏ」は、指定された位置がゼロ定数以外の値を含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｌｏｓｔ」は、指定された位置が失われたメモリとしてマークされているかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「ｉｎｔ＿ｔｏ＿ｆｌｏａｔ」は、指定された位置の値を、整数表示から浮動小数点表示に変換するよう活力ユニットに命令するものである。活力プリミティブ「ｆｌｏａｔ＿ｔｏ＿ｉｎｔ」は、指定された位置の値を、浮動小数点表示から整数表示に変換するよう活力ユニットに命令するものである。活力プリミティブ「ｓｔａｔｅ＿ｅｑ」は、指定された位置が、所与の状態と等しい状態にある資源を表すかどうかを示すよう活力ユニットに命令するものである。最後に、活力プリミティブ「ｓｔａｔｅ＿ｎｅ」は、指定された位置が、所与の状態と等しくない状態にある資源を表すかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブを評価する際にはしばしば、ある位置によってモデル化されたメモリのタイプの特定の特徴を理解することが必要となる。様々なタイプのモデル化されたメモリについては、「メモリ作成ユニット１５００」の見出しで既に考察した。様々なタイプのモデル化されたメモリのそれぞれについて、対応するメモリ情報ブロック３４００（第３４図）が存在する。メモリ情報ブロック３４００は、対応するメモリ・タイプの特定の特徴を識別する。メモリ情報ブロック３４００は下記のフィールドを含む。「メモリ・タイプ」３４０２、「印刷可能メモリ名」３４０４、「定数フラグ」３４０６、「デリファレンス・タイプ」３４０８、「開始時初期化フラグ」３４１０、「開始時有効フラグ」３４１２、「ロスト・フラグ」３４１４、「自由許可フラグ」３４１６、「フリー・エラー・コード」３４１８、「資源フラグ」３４２０、「ログ試験フラグ」３４２２、「初期化」３４２４、「有効」３４２６、および「ヌル」３４２８。
フィールド「メモリ・タイプ」３４０２は、瞬間メモリ・タイプ情報ブロック３４００（瞬間メモリ・タイプとも呼ばれる）が表すメモリのタイプを識別する。フィールド「印刷可能メモリ名」３４０４は、印刷可能なフォーマットの瞬間メモリ・タイプの名前を指定する。フィールド「印刷可能メモリ名」３４０４は、エラー・メッセージの生成に使用される。フラグ「定数フラグ」３４０６は、瞬間メモリ・タイプが定数であるときにオンにセットされる。メモリ・タイプが定数である場合には、そのタイプの位置は割当てを受けることができない。フィールド「デリファレンス・タイプ」３４０８は、適用可能であるときに、瞬間メモリ・タイプが指すメモリ・タイプを示す。
フラグ「開始時初期化フラグ」３４１０は瞬間メモリ・タイプが初期化されたときにオンにセットされる。フラグ「開始時有効フラグ」３４１２は、瞬間メモリ・タイプが有効ポインタであるときにオンにセットされる。フラグ「ロスト・フラグ」３４１４は、瞬間メモリ・タイプが失われる可能性があるときにオンにセットされる。フラグ「自由許可フラグ」３４１６は、瞬間メモリ・タイプを解放することができるときにオンにセットされる。フィールド「自由エラー・コード」３４１８は、適用可能である場合には、瞬間メモリ・タイプを解放する際に生成されるエラー・コードを指定する。
フラグ「資源フラグ」３４２０は、瞬間メモリ・タイプが資源を参照するときにオンにセットされる。フラグ「ログ試験フラグ」３４２２は、瞬間メモリ・タイプの位置に対して行われる試験をログしなければならないときにオンにセットされる。フィールド「初期化」３４２４は、ある位置を、初期化されたものであるとして瞬間メモリ・タイプから識別することができるかどうかを指定する。フィールド「有効」３４２６は、ある位置を、有効であるとして瞬間メモリ・タイプから識別することができるかどうかを指定する。フィールド「ヌル」３４２８は、ある位置を、ヌルであるものとして瞬間メモリ・タイプから識別することができるかどうかを指定する。
フェッチ値は、記憶された値に含まれる値の作業用コピーとして使用される。フェッチ値をフェッチ値ブロック３５００で説明する。フェッチ値ブロック３５００は、第３５図に示してある。フェッチ値ブロック３５００は下記のフィールドを含む。「バイト数」３５０２、「正確な値が既知のフラグ」３５０４、「正確値ポインタ」３５０６、「述語集合ポインタ」３５０８、「値の形式」３５１０、「実数の値」３５１２、「無符号整数の値」３５１４、「資源タイプ」３５１６、「資源状態」３５１８、「初期化フラグ」３５２０、「有効ポインタ」３５２２、「非ゼロ・フラグ」３５２４、「新規述語フラグ」３５２６、「変更フラグ」３５２８、「想定フラグ」３５３０、「ｓｖｓポインタ」３５３２、「ｓｖｓオフセット」３５３４、「位置からのフラグ」３５３６、「位置」３５３８、「チャンク起点」３５４０、「メモリ・タイプ」３５４２、「ｓｖサブセット・ポインタ」３５４４、「式ポインタ」３５４６、および「デリファレンス・フラグ」３５４８。
フィールド「バイト数」３５０２は、記述される値が表すバイト数を指定する。フラグ「正確な値が既知のフラグ」３５０４は、記述される値が完全に既知であるときにオンにセットされる。フィールド「正確値ポインタ」は、適用可能であるときに、正確な値を含むバイト・アレイを指す。指されるバイト・アレイのサイズは、フィールド「バイト数」３５０２に含まれる数と等しい。フィールド「述語集合ポインタ」３５０８は、瞬間フェッチ値に適用される全ての述語の集合を指す。フィールド「値の形式」３５１０は、記述される値の形式のタイプを示す。フィールド「実数の値」３５１２は、フィールド「値の形式」３５１０が実数値を示すときに、記述される値を実数形式で指定する。フィールド「無符号整数の値」３５１４は、フィールド「値の形式」３５１０が実数値以外を示すときに、記述される値を整数形式で指定する。
フィールド「資源タイプ」３５１６は、適用可能である場合には、記述される値に関連した資源のタイプを示す。フィールド「資源状態」３５１８は、適用可能である場合には、記述される値に関連した資源の状態を示す。フラグ「初期化フラグ」３５２０は、記述される値が初期化されたときにオンにセットされる。フィールド「有効ポインタ」３５２２は、フェッチ値が有効ポインタであるかどうかを示す。フラグ「非ゼロ・フラグ」３５２４は、真であるときには、フェッチ値がゼロ定数でないことを知らせる。フラグ「新規述語フラグ」３５２６は、「述語集合ポインタ」３５０８が指す述語の集合に、任意の述語が追加されているかどうかを示す。フラグ「変更フラグ」３５２８は、フェッチ値が任意の活力プリミティブによって変更されているかどうかを知らせる。フェッチ値は、活力プリミティブによって変更されているときには、メモリ・モデルに戻して記憶しなければならない。フラグ「想定フラグ」３５３０は、フェッチ値が活力プリミティブによって想定されているかどうかを示す。フェッチ値は、活力プリミティブによって想定されているときには、対応する記憶された値に上書きしなければならない。
フィールド「ｓｖｓポインタ」３５３２は、フェッチ値の発生元となる、記憶された値のセットを指す。フィールド「ｓｖｓオフセット」３５３４は、フィールド「ｓｖｓポインタ」３５３２が指す記憶された値のセット中のフェッチ値の開始オフセットを含む。フラグ「位置からのフラグ」は、フェッチ値の内容がモデル化されたメモリの位置から来たものであるかどうかを示す。フィールド「位置」３５３８は、フェッチ値の発生元となるモデル化されたメモリ中の位置を指す。フィールド「チャンク起点」３５４０は、フィールド「ｓｖｓポインタ」３５３２が指す記憶された値のセットを指すチャンク１７００によって指される起点コンテキスト構造１６００を指す。フィールド「メモリ・タイプ」３５４２は、どのような種類のメモリがフェッチ値によって使用されるかを指定する。
フィールド「ｓｖサブセット・ポインタ」３５４４は、フィールド「ｓｖｓポインタ」３５３２が指す記憶された値のセットに含まれる記憶された値のサブセットを含む集合を指す。フィールド「式ポインタ」３５４６は、フェッチ値を含む式を表す現在の構文解析ツリー構造３０４中のノードを指すポインタを含む。フラグ「デリファレンス・フラグ」３５４８は、フェッチ値が実際に、フィールド「式ポインタ」３５４６が示す式中の値のデリファレンスであるかどうかを示す。
述語は、左側オペランドおよび場合によっては右側オペランドに適用される活力プリミティブの特定の適用についての情報を記憶している。述語は、述語ブロック３６００で表される。述語ブロック３６００は下記のフィールドを含む。「プリミティブ」３６０２、「無符号オペランド・フラグ」３６０４、「ｓｖｓポインタ」３６０６、「ｓｖオフセット」３６０８、「ｓｖカウント」３６１０、「引数」３６１２、「引数オフセット」３６１４、「引数長さ」３６１６、「資源タイプ」３６１８、および「資源状態」３６２０。
フィールド「プリミティブ」３６０２は、この述語が記録する活力プリミティブのタイプを指定する。フラグ「無符号オペランド・フラグ」３６０４は、この述語が表す活力プリミティブ（表された活力プリミティブと呼ぶ）が無符号オペランドに適用されたかどうかを示す。フィールド「ｓｖｓポインタ」３６０６は、表された活力プリミティブが適用される値に対応する記憶された値のセットを指す。フィールド「ｓｖオフセット」３６０８は、表された活力プリミティブが適用される、「ｓｖｓポインタ」３６０６が指す記憶された値のセットの中の、第１の記憶された値のオフセットを指定する。フィールド「ｓｖカウント」３６０８は、表された活力プリミティブが適用される記憶された値の数を指定する。フィールド「引数」３６１２は、適用可能である場合には、述語の右側オペランドを指す。フィールド「引数オフセット」３６１４は、右側オペランドについての第１の記憶された値を指す。フィールド「引数長さ」３６１２は、右側オペランドを表すために使用される記憶された値の数を指定する。フィールド「資源タイプ」３６１８は、活力プリミティブが資源プリミティブであるときに、資源のタイプを示す。フィールド「資源状態」３６２０は、活力プリミティブが資源プリミティブであるときに、資源状態を示す。
活力プリミティブ試験ユニットは、メモリ・モデルの内容に対して試験を実行する。付録Ｄは、活力プリミティブ試験ユニットを実施するために使用される１実施形態の疑似コードを含む。活力プリミティブ評価ユニットは、メモリ・モデルを更新して、指定されたオペレーションを評価した結果を反映する。付録Ｄは、活力プリミティブ評価ユニットを実施するために使用される１実施形態の疑似コードを含む。活力想定ユニットは、メモリ・モデルを更新して、未解決な選択点をＣＰＨ選択条件ユニットで解決した結果を反映する。付録Ｄは、活力想定ユニットを実施するために使用される１実施形態の疑似コードを含む。
障害インジケータ・オブジェクト７１２
障害インジケータ・オブジェクト７１２は、障害インジケータ１０６を生成して、分析器２０２が検出したプログラミング・エラーを報告する。障害インジケータ・オブジェクト７１２の処理は、エラー生成ユニットによって実行される。エラー生成ユニットは、論理流れ図３７００（第３７図）として詳細に示してある。第３７図の実施形態では、障害インジケータ１０６はエラー・メッセージの形になっている。
エラー生成ユニット中の処理は、検出されたプログラミング・エラーがメモリまたは資源の漏れであるかどうかを決定する漏れエラー判断３７０２（以下「判断３７０２」とする）から開始する。エラーが漏れである場合には、処理制御は、パス終了タイプを決定する処置３７０４（以下「処置３７０４」とする）に移ることになり、そうでない場合には、処理制御は、ｍａｉｎ関数中のローカル・エラーの判断３７１０（以下「判断３７１０」とする）に移る。
処置３７０４は、漏れを生じるパスがどのようにして終了したかを決定する。パスは３通りの方法、すなわち出口、ロングジャンプ、またはリターンの１つで終了することができる。パス終了のタイプが発見された後で、処理制御は、抑制終了タイプの判断３７０６（以下「判断３７０６」とする）に移る。判断３７０６は、構成オプションが、漏れを生じたパスの方法で、終了したパスの漏れエラーを抑制するようにセットされているかどうかを決定する。このような構成オプションがセットされている場合には、処理制御は、論理流れ図３７００に従って処理を終了するリターン３７０８に移る。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。漏れエラーの報告を行う構成オプションは、「ｌｅａｋｓ＿ｏｎ＿ｅｘｉｔ」、「ｌｅａｋｓ＿ｏｎ＿ｌｏｎｇｊｕｍｐ」、および「ｌｅａｋｓ＿ｏｎ＿ｒｅｔｕｒｎ」である。構成オプションについてのこれ以上の情報は、付録Ｂに与える。構成オプションが漏れエラー・メッセージを抑制するようにセットされていない場合には、処理は判断３７１０に移る。
判断３７１０は、現在の関数名が「ｍａｉｎ」であるかどうか、またこの関数が、「ｍａｉｎ」関数にローカルなメモリにポインタを戻しているかどうかを決定する。このような（判断３７１０が真であると決定した）場合には、処理は、論理流れ図３７００に従って処理を終了するリターン３７１２に移る。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。判断３７１０が偽であると決定したときには、処理制御は、コンテキスト情報を得る処置３７１４（以下「処置３７１４」とする）に移る。
処置３７１４は、生成されたエラー・メッセージに記入するために使用することになるコンテキスト情報を収集する。コンテキスト情報により、ユーザは、コード中のプログラミング・エラーを突き止めることができる。処置３７１４は、障害のある関数を含むファイルのファイル名、および関数内のエラーが検出された行番号を決定する。処置３７１４は、エラーのある関数の名前、エラーが発生したパスの番号、およびエラーを含む式も収集する。関数のエミュレーション中にエラーが発生した場合には、処置３７１４は、エミュレートした関数の名前と、エミュレートした関数を含むファイルの名前と、エミュレートされた関数中のエラーが検出された行に対応するそのファイル中の行番号を収集する。処置３７１４でのデータ収集が完了した後で、処理は、構成オプション抑制判断３７１８（以下「判断３７１８」とする）に移る。
判断３７１８は、検出されたエラーの報告を防止する構成オプションが使用可能になっているかどうかを決定する。このような構成オプションが指定されている（判断３７１８が真であると決定した）ときには、処理は、リターン３７２０に移り、論理流れ図３７００に従って処理を終了する。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。関連のある構成オプションは、特定のエラー・メッセージのみの生成を指示する「報告」、および特定のエラー・メッセージの抑制を指示する「抑制」である。特定の構成オプションについてのこれ以上の情報は、付録Ｂに与える。判断３７１８が偽であると決定したときには、処理制御は重複エラー判断３７２２（以下「判断３７２２」とする）に移る。
判断３７２２は、検出されたエラーが以前に報告されたエラーとの重複であるかどうかを決定する。エラーは、異なる３つの形で重複エラーに分類される。第１に、エラーは、以前のエラーが同じファイル名および文中に発生した場合に重複となる。第２に、エラーは、以前に報告されたミッシング・モデルについてのミッシング・モデル・エラーである場合に重複となる。第３に、エラーは、検出されたエラーを引き起こした記憶された値のセットが、以前に報告されたエラーを引き起こしたものと同じ記憶された値のセットである場合に重複となる。検出されたエラーが重複エラーである（判断３７２２が真であると決定した）場合には、処理は、リターン３７２４に移り、論理流れ図３７００に従って処理を終了する。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。判断３７２２が偽であると決定したときには、処理制御はエラー報告処置３７２６（以下「処置３７２６」とする）に移る。
処置３７２６は、検出されたエラーのタイプに対応するエラー・メッセージを印刷する。印刷する前に、エラー・メッセージには、処置３７１４で収集されたコンテキスト情報が記入される。エラー・メッセージが印刷された後で、論理流れ図３７００による処理、したがってエラー生成ユニットは終了する。終了すると、エラー生成ユニットは、制御が発生したサイトに処理制御を戻す。
自動モデル化
概説
モデル１１８は、対応する関数の動作を概略的に表すものでる。モデル１１８は、関数の外部に可視の動作、すなわち関数の呼出し元に見える動作のみを含む。
別の関数を呼び出す関数を分析するときには、分析器２０２は、呼び出される関数のモデルを使用してその動作を決定する。これにより分析は非常に簡単になり、速度も上がり、分析器２０２は、呼び出される関数のソース・コードを必要としなくなり、その分析に時間をかける必要もなくなる。
モデルは、分析器２０２によって自動的に生成される。分析器は、関数を分析する際にその関数が何を行うかを記憶し、その関数の分析が完了するときに、その関数のモデル１１８を構築する。
分析器は、付録Ｇに記載する特殊なモデル化言語でモデル１１８を読み取り、これに書き込む。ユーザがその言語でモデル１１８に書き込むこともできるが、これは、ソースのない、したがって分析し、自動的にモデル化することができない関数について行われる。
モデル化の概念
エクスターン、制約、結果、アウトカム、および保護の５つの基本的なモデル化の概念がある。
エクスターンは、単なる外側から見ることのできる関数中の変数である。具体的に言うと、これらはパラメータ変数、大域変数、および静的変数である。モデル１１８は外部から可視の動作しかカプセル化しないので、これらはモデル１１８中に現れることができる変数のみとなる。
制約は、関数が入力されたときに真とならなければならない条件である。例えばそのパラメータの１つが有効ポインタであると関数が想定している場合には、関数のモデル１１８はそれを必要とする制約を含むことになる。制約は、関数が呼び出され、モデル１１８が評価されるときに試験されることになり、その制約が当てはまらない場合には、分析器２０２がエラーを報告することになる。
制約とは対照的に、結果は、関数が戻したときに真となる条件である。例えば関数がゼロを戻した場合には、それが結果になることになる。次いで結果は、分析器２０２で後続の分析に使用される。例えば、呼び出された関数の戻し値がその後で変数に割り当てられた場合には、呼び出された関数のモデル１１８が戻す結果は分析中の変数に割り当てられることになる。
アウトカムは、関数が分割されたケースである。ほとんどの関数は条件（ｉｆ−ｔｈｅｎ、ｓｗｉｔｃｈ、ｆｏｒ  ｌｏｏｐなど）を含み、この条件付き実行はモデル１１８の中で表されなければならず、そうでなければ、モデル化されたあらゆる関数は呼び出されるたびに同じことを行うことになる。これに対して、モデル１１８はそれらがモデル化した関数より単純になる必要があり、そうでなければ、それらは関数自体より速く評価することができないことになる。関数は、それが戻す値に基づいてケースに分割され、これらの各ケースがアウトカムとなる。例えば関数ｍａｌｌｏｃは、それが成功した場合にはポインタを、失敗した場合には０（ヌル）を、割り振られたメモリに戻す。ｍａｌｌｏｃのモデルは２つのアウトカムを有する。より一般的には、分析器２０２は戻し値を以下のケースに分割する。
・関数が０を戻す
・関数が１を戻す
・関数が−１を戻す
・関数が上記３つのうちの１つに制限されない値を戻す
・戻し値が未知である
・関数が値を戻さない（ボイド関数の場合）
・関数がロングジャンプする
・関数が終了する
これらのアウトカム・タイプは、それらが速度（いくつかのアウトカム・タイプ）と情報の完全さ（多くのアウトカム・タイプ）の間の妥当なトレードオフを表すことから選択した。
モデルが複数のアウトカムを有するときには、分析器２０２は、どのアウトカムを使用するか選択しなければならない。この選択はしばしば入力値に基づいて行われる。保護は、こうした選択を表すために使用される機構である。例えば、以下の関数は、１を戻す場合と０を戻す場合の、２つのアウトカムを有する。
0004633203.tif 000007
この関数は、パラメータが０である場合には１しか戻さず、パラメータが０でない場合には０しか戻さない。各アウトカムは適当な条件を具体化した保護を有することになる。
保護は制約と全く同じ形をしているが、それらの意味は異なる。制約は「このアウトカムが選択され、その制約の条件が当てはまらない場合に、エラーを報告する」という意味であるが、保護は、「その保護の条件が当てはまらない場合には、このアウトカムを選択してはならない」という意味となる。条件を評価することができない場合（例えば上記の値１が未知である場合）には、ある条件が想定され（ここではｉの値）、あるアウトカムが選択される。
自動モデラ
自動モデラは、関数を分析する際にモデル１１８を構築する。現在の関数を介した各パスが終了するとき、処置１２１６中に、メモリ・モデル中の構造を走査し、制約および保護を決定する各外部について実行された試験と、結果を決定する各外部に対して行われた変更（割当てなど）とを決定する。これらの制約および結果はアウトカムにパッケージされる。現在の関数についての分析が終了するとき、処置１１１４内で、全ての個別のパスのアウトカムを操作し、無関係のオペレーションを除去し、重複したアウトカムを削除する。次いで個別のアウトカムを、エクスターンのリストと共に現在の関数のモデルにパッケージする。付録Ｅは、自動モデラを実施するために使用される一実施形態の擬似コードを含む。
マイクロフィッシュの付録Ａのコンピュータ・プログラムは、一実施形態では、ＵＮＩＸ  Ｓｏｌａｒｉｓ  ２．５(R)オペレーティング・システムと、米国カリフォルニア州、Ｍｏｕｎｔａｉｎ  ＶｉｅｗのＳｕｎ  Ｍｉｃｒｏｓｙｓｔｅｍｓから市販されているＳｕｎ  ＳＰＡＲＣｓｔａｔｉｏｎTM５などのワークステーションを備えたＳＰＡＲＣｗｏｒｋｓTM３．０．１コンパイラおよびリンカとを使用してコンパイルおよびリンクされた。第２の実施形態では、マイクロフィッシュの付録Ａのコンピュータ・プログラムは、米国Ｗａｓｈｉｎｇｔｏｎ州、ＲｅｄｍｏｎｄのＭｉｃｒｏｓｏｆｔ  Ｃｏｒｐｏｒａｔｉｏｎから市販されている、やはりＭｉｃｒｏｓｏｆｔ  Ｃｏｒｐｏｒａｔｉｏｎから市販されているＭｉｃｒｏｓｏｆｔ  Ｗｉｎｄｏｗｓ  ＮＴTM３．５．１を使用してパーソナル・コンピュータ上で使用することができる、Ｍｉｃｒｏｓｏｆｔ  Ｖｉｓｕａｌ  Ｃ＋＋  ４．０が統合された開発環境を使用してコンパイルおよびリンクされた。このようなパーソナル・コンピュータとしては、米国サウスダコタ州、Ｎｏｒｔｈ  Ｓｉｏｕｘ  ＣｉｔｙのＧａｔｅｗａｙ  ２０００  Ｉｎｃ．から市販されているＧａｔｅｗａｙ  Ｇ６−２０００がある。マイクロフィッシュの付録Ａのコンピュータ・プログラムが適合する特定のコンピュータ言語、およびマイクロフィッシュの付録Ａのコンピュータ・プログラムによって規定されるコンピュータ・プロセスが実行されるコンピュータ・システムは、本発明の重要な面ではない。本発明の開示に鑑みて、当業者なら、様々なコンピュータ言語および／または様々なコンピュータ・システムを使用して本発明を実施することができる。
上記の記述は単なる例示であり、制限的なものではない。例えば、開示の実施形態ではＣコンピュータ言語に従って関数を分析するが、本発明の原理は、上記のものも含めて、ただしそれらに制限されることなく、その他のコンピュータ命令プロトコルに適用することができる。本発明は下記の請求の範囲によってのみ制限される。
0004633203.tif 000008
0004633203.tif 000009
0004633203.tif 000010
0004633203.tif 000011
0004633203.tif 000012
0004633203.tif 000013
0004633203.tif 000014
0004633203.tif 000015
0004633203.tif 000016
0004633203.tif 000017
0004633203.tif 000018
0004633203.tif 000019
0004633203.tif 000020
0004633203.tif 000021
0004633203.tif 000022
0004633203.tif 000023
0004633203.tif 000024
0004633203.tif 000025
0004633203.tif 000026
0004633203.tif 000027
0004633203.tif 000028
0004633203.tif 000029
0004633203.tif 000030
0004633203.tif 000031
0004633203.tif 000032
0004633203.tif 000033
0004633203.tif 000034
0004633203.tif 000035
0004633203.tif 000036
0004633203.tif 000037
0004633203.tif 000038
0004633203.tif 000039
0004633203.tif 000040
0004633203.tif 000041
0004633203.tif 000042
0004633203.tif 000043
0004633203.tif 000044
0004633203.tif 000045
0004633203.tif 000046
0004633203.tif 000047
0004633203.tif 000048
0004633203.tif 000049
0004633203.tif 000050
0004633203.tif 000051
0004633203.tif 000052
0004633203.tif 000053
0004633203.tif 000054
0004633203.tif 000055
0004633203.tif 000056
0004633203.tif 000057
0004633203.tif 000058
0004633203.tif 000059
0004633203.tif 000060
0004633203.tif 000061
0004633203.tif 000062
0004633203.tif 000063
0004633203.tif 000064
0004633203.tif 000065
0004633203.tif 000066
0004633203.tif 000067
0004633203.tif 000068
0004633203.tif 000069
0004633203.tif 000070
0004633203.tif 000071
0004633203.tif 000072
0004633203.tif 000073
0004633203.tif 000074
0004633203.tif 000075
0004633203.tif 000076
0004633203.tif 000077
0004633203.tif 000078
0004633203.tif 000079
0004633203.tif 000080
0004633203.tif 000081
0004633203.tif 000082
0004633203.tif 000083
0004633203.tif 000084
0004633203.tif 000085
0004633203.tif 000086
0004633203.tif 000087
0004633203.tif 000088
0004633203.tif 000089
0004633203.tif 000090
0004633203.tif 000091
0004633203.tif 000092
0004633203.tif 000093
0004633203.tif 000094
0004633203.tif 000095
0004633203.tif 000096
0004633203.tif 000097
0004633203.tif 000098
0004633203.tif 000099
0004633203.tif 000100
0004633203.tif 000101
0004633203.tif 000102
0004633203.tif 000103
0004633203.tif 000104
0004633203.tif 000105
0004633203.tif 000106
0004633203.tif 000107
0004633203.tif 000108
0004633203.tif 000109
0004633203.tif 000110
0004633203.tif 000111
【図１】
0004633203.tif 000112
【図５】
0004633203.tif 000113
【図２】
0004633203.tif 000114
【図３】
0004633203.tif 000115
【図４】
0004633203.tif 000116
【図６】
0004633203.tif 000117
【図７】
0004633203.tif 000118
【図８】
0004633203.tif 000119
【図９】
0004633203.tif 000120
【図１０】
0004633203.tif 000121
【図１１】
0004633203.tif 000122
【図１２】
0004633203.tif 000123
【図１３】
0004633203.tif 000124
【図１４ａ】
0004633203.tif 000125
【図１４ｂ】
0004633203.tif 000126
【図１５】
0004633203.tif 000127
【図１６】
0004633203.tif 000128
【図１７】
0004633203.tif 000129
【図１８】
0004633203.tif 000130
【図１９】
0004633203.tif 000131
【図２０】
0004633203.tif 000132
【図２１】
0004633203.tif 000133
【図２２】
0004633203.tif 000134
【図２３】
0004633203.tif 000135
【図２４】
0004633203.tif 000136
【図２５ａ】
0004633203.tif 000137
【図２５ｂ】
0004633203.tif 000138
【図２６】
0004633203.tif 000139
【図２８】
0004633203.tif 000140
【図２７】
0004633203.tif 000141
【図２９】
0004633203.tif 000142
【図３０ａ】
0004633203.tif 000143
【図３０ｂ】
0004633203.tif 000144
【図３１】
0004633203.tif 000145
【図３２】
0004633203.tif 000146
【図３３】
0004633203.tif 000147
【図３４】
0004633203.tif 000148
【図３６】
0004633203.tif 000149
【図３５】
0004633203.tif 000150
【図３７】
0004633203.tif 000151