JP4633203B2 - シミュレートされたプログラムの実行エラーの検出方法および装置 - Google Patents
シミュレートされたプログラムの実行エラーの検出方法および装置 Download PDFInfo
- Publication number
- JP4633203B2 JP4633203B2 JP50825598A JP50825598A JP4633203B2 JP 4633203 B2 JP4633203 B2 JP 4633203B2 JP 50825598 A JP50825598 A JP 50825598A JP 50825598 A JP50825598 A JP 50825598A JP 4633203 B2 JP4633203 B2 JP 4633203B2
- Authority
- JP
- Japan
- Prior art keywords
- action
- function
- computer program
- pointer
- model
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Expired - Lifetime
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3604—Software analysis for verifying properties of programs
- G06F11/3608—Software analysis for verifying properties of programs using formal methods, e.g. model checking, abstract interpretation
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Debugging And Monitoring (AREA)
- Stored Programmes (AREA)
Description
付録Aは、本開示の一部であり、合計で2146個のフレームを有する22枚のマイクロフィッシュ・シートからなるマイクロフィッシュの付録である。マイクロフィッシュの付録Aは、本発明の一実施態様におけるコンピュータ・プログラムおよび関連データのリストである。この実施形態については以下でより完全に説明する。
本特許文書の開示の一部には、著作権保護を受ける内容が含まれる。著作権所有者は、特許商標庁の特許ファイルに記録された本特許文書または本特許開示を正確に複製することには異議を唱えないが、それ以外の場合にはすべての著作権を留保する。
発明の背景
発明の分野
本発明は、コンピュータ・プログラムの分析に関し、詳細には、構造メモリ・モデルに対してコンピュータ・プログラムをシミュレートされた実行の効果を分析することによってコンピュータ・プログラムのプログラミング・エラーを検出することに関する。
背景
コンピュータ・プログラムを開発する際には、完成したコンピュータ・プログラムの正しさを保証することに多大な努力が払われる。コンピュータ・プログラムの目的は、指定された入出力関数をインプリメントすることである。コンピュータ・プログラムの正しさとは、プログラムの仕様、設計、インプリメントにおいてエラーが生じない程度である。コンピュータ・プログラムのエラーを検出する最も一般的な2つの方法は、コンパイル時検査および実行時検査である。
コンパイル時検査とは、形態、構造、または内容に基づいてコンピュータ・プログラムを評価するプロセスである。コンパイル時検査は、プログラムが実行される前に確立できる特性を試験する。「構文検査」は、コンパイル時検査の一形態であり、言語に関して定義された構造規則または文法規則との整合を検証する。たとえば、周知のCコンピュータ言語で書かれたコンピュータ・プログラムでは、文B+C=Aを使用した場合、正しい形式はA=B+Cであるためにエラーが生じる。構文検査は、Richard ConwayおよびDavid Gries著「An Introduction to Programming」(Winthrop Publishers,Inc.、1979年)に詳しく記載されている。
「データ・フロー分析」は、他の種類のコンパイル時検査であり、コンピュータ・プログラム内でデータ転送、使用、変換が実行されるシーケンスを分析してプログラミング・エラーを検出する。データ・フロー分析には、制御フロー情報を使用することが含まれる。「制御フロー」は、コンピュータ・プログラムを実行する際に文が実行されるシーケンスである。制御フローは、「制御フロー・パス」、または単に「コード・パス」とも呼ばれる。データ・フロー分析は、代入を行う前に変数を使用することや、、2回連続して変数に代入することや、使用されることのない変数に値を代入することなどのエラーを検出することができる。
コンパイル時検査モジュールの最大の欠点は、このような方法ではコンピュータ・プログラム実行の結果が考慮されないために生じる。コンパイル時検査は、プログラム実行の動的効果を考慮せずに判定できることに限られる。たとえば、カリフォルニア州マウンテンビューのSun Microsystems社から市販されているSPARCworksTM3.0.1.1のプログラミング環境で使用できるlintコンパイル時チェッカは、コンピュータ・コードによる動的制御フローにかかわらずにコンピュータ・コードを分析する。この欠点のために、lintは、使用中の値を初期設定される前に報告する。したがって、実際には、報告される値は使用中の値とは異なる。
コンパイル時検査によって生成されるエラー・メッセージは通常、内容が不十分であるか、あるいは過剰である。コンピュータ・プログラムの特定の関数は、ある資源が有効である場合、その資源を検査の前に使用することができる。この関数の外部で資源の有効性が検査されない場合、プログラム終了エラーの可能性が報告されないため、データ構造が破壊され、場合によっては貴重なデータが失われる恐れがある。しかし、この関数の前に資源の有効性を検査した場合、エラーが報告されると、この関数の分析が擬エラーで混乱し、大規模なプログラムではコンピュータ・プログラムの分析が無用になる恐れがある。
コンパイル時分析方法で報告される他の種類の擬エラーは、制御フローが進行できない命令の「明らかな」エラーである。文が実行されるシーケンスは多くの場合、特定の変数に関連する特定の値に依存する。コンパイル時検査方法は一般に、特定のコード・パスが実行されるかどうか、あるいはプログラム制御フローがどんな特定の環境の下でコード・パスを流れるかを判定できないので、文は常に実行されるものと仮定する。
実行時検査は、他の主要な種類のプログラミング・エラー検出方法であり、コンピュータ・プログラムを実行中の動作に基づいて評価するプロセスである。実行時検査では、既知の1組の入力を用いてコンピュータ・プログラムを実行し、プログラム結果を予期される結果と比較して検証する。この1組の試験入力、実行条件、予期される結果を「テスト・ケース」と呼ぶ。多くの場合、エラーを見つけるのを助けるために、それぞれの異なる点での選択された変数の値を示すプリントアウト(トレース)が作成される。
概念は簡単であるが、実行時検査の有用性は、コンピュータ・プログラムの複雑さによって制限される。テスト・ケースを構成し、作成し、実行するには多大な労力が必要である。多大な労力を払ったにもかかわらず、実行時検査のエラー検出関数は、選択された特定の1組の入力によって実行されるコード・パスに限られる。ほとんどの最も簡単なコンピュータ・プログラムでは一般に、すべての可能な制御フロー・パスを実行することは実際的ではない。さらに、実行時検査では、コンピュータ・プログラムが完全であり、実行準備が完了している必要がある。関数を分析するにはその関数を実行しなければならないので、関数を、完全なプログラムに組み込むだけでなく試験するには、関数に必要な実行環境を与えるプログラム・シェルを構築する追加の労力が必要である。
典型的なプログラミング・エラー検出方法の欠点を解消する1つの方法が、「Computer Process Resource Modelling Method and Apparatus」と題する米国特許出願第08/289148号で本出願人によって提示されている。この出願は、1994年8月10日に出願され、本出願人に譲渡され、引用によって明示的に本明細書と合体されている。このプログラミング・エラー検出方法は、プログラム資源の状態に対するプログラム命令の効果を追跡することによってコンピュータ・プログラムの構成要素を分析する。各資源は、各状態の間のいくつかの状態および遷移によって表される所定の動作を有する。しかし、状態マシンを維持し使用することは面倒であるので、コンピュータ・プロセス資源モデリングの能力はスプリアス・エラーを抑制し、詳細なエラー・メッセージを生成することに限られる。さらに、方法自体の複雑さのために、この方法を具体化する構造を維持し、かつこの方法を新しい種類のプログラミング・エラーおよびプログラミング言語に拡張することは困難である。
実行されるプログラム命令の動作を考慮し、コンピュータ・プログラム内のほぼすべての可能な制御フロー・パスを自動的に考慮し、コンピュータ・プログラムの個々の関数を分析することのできるプログラミング・エラー検出方法が必要である。さらに、呼出し関数を分析する際に被呼関数の動作を考慮するプログラミング・エラー検出方法が必要である。必要とされるプログラミング・エラー検出方法は、維持し、かつ新しいプログラミング言語および異なる種類のエラーに拡張するのも容易でなければならない。必要とされる方法は、スプリアス・エラーを最小限に抑え、詳細なエラー・メッセージを生成することもできるべきである。
発明の概要
本発明によれば、プログラム文の実行をシミュレートすることによってコンピュータ・プログラムの実行時動作を分析するコンピュータ・プログラム・エラー検出システムが提供される。特に、このシステムを使用して、コンピュータ・システム内の関数のサブセットのみ、あるいはプログラム全体を分析することができる。一実施態様では、オブジェクト・ベースの設計方法を使用してシステムの保全性が高められ、同時に高い拡張性が与えられる。
本発明の一実施態様では、コンピュータ・プログラムがプリプロセッサに入力される。プリプロセッサには、構成ファイル、ヘッダ・ファイル、コマンド行情報に含まれる指定された構成オプションも入力される。プリプロセッサは、コンピュータ・プログラムを内部フォーマット構造(構文解析ツリー構造)に変換する。構文解析ツリー構造は、コンピュータ・プログラム内で定義されたすべての関数のリストと共に中間ファイルに変換される。この中間ファイル、構成オプション、コマンド行情報、外部動作モデルは分析エンジンに変換される。
分析エンジン処理ではまず、構成オプションが受け入れられる。構成オプションは、分析エンジンによって実行される分析を制御する。制御構成オプションが決定されると、中間ファイルからコンピュータ・プログラムの内部フォーマット構造が取り込まれる。分析エンジンは、やはり中間ファイルから、コンピュータ・プログラムによって定義されたすべての関数を識別する。コンピュータ・プログラムの内部フォーマット構造が分析され、すべての関数呼出しが識別される。関数分析のスケジューリングは識別された関数呼出しの順序によって制御される。本発明の他の実施態様では、内部フォーマット構造の代わりにコンピュータ・プログラムの異なる表現を使用することができる。たとえば、コンピュータ・プログラムを表すソース・コードを使用することができる。
分析エンジンは、関数を分析する前に、識別された被呼関数に対応するすでに構築されている外部動作モデルを見つけて取り込む。収集された外部動作モデルは、モデル・テーブル・エントリによって表される。各モデル・テーブル・エントリは、モデル・テーブルとして収集される。被呼関数に関する外部動作モデルが見つからない場合、その関数は、欠落しているモデルによって表される。モデル・テーブルは、関数分析中に外部動作モデルを参照することを可能にする。
コンピュータ・プログラムによって定義された各関数の分析はループで実行される。関数分析の開始時には、その関数に対応する内部フォーマット構造がメモリに読み込まれる。分析エンジンは、最大数のパスに到達するか、あるいは分析するパスがもはやなくなるまで、関数を通るコード・フロー・パスを通ることによってこの関数を分析する。パスの最大数は、分析エンジン処理の限界を決定するために構成オプションを用いて設定される。決定的選択点履歴を使用して制御フロー・パスが選択される。いくつかの異なる制御フロー・パスを通る関数のシミュレートされた実行は、CPHツリーによってモデル化される。制御フロー・パスは未処理の選択点を含むことができる。これは、制御フロー・パス内に処理できない条件文または述語があることを意味する。CPHツリー内のノードを使用して、未処理の各選択点が表される。未処理の選択点の分解能をシミュレートするように、ノードのエッジがランダムに選択される。CPHツリー内でパスが選択された後、このパスが分析される。エッジをランダムに選択すると、制御フロー・パス内での文の効果を表す構造メモリ・モデルを更新することによって記憶されるプログラム変数に関する意味が生じる。
選択したすべてのパスが分析された後、分析中の関数の外部動作モデルが収集される。分析中の関数がもはや必要なくなると、この関数の内部フォーマット構造がメモリから解放される。最後に、オートモデラがすべての個々のパス結果を走査し、無関係の動作を削除し、二重の結果を削除する。オートモデラは次いで、残りの結果をパッケージして、分析中の関数の外部動作モデルを生成する。
特定の制御フロー・パスを分析するには、制御フロー・パスに沿って各文をシミュレートする必要がある。分析エンジンは、パス分析の開始時に、分析中の関数に関してのみ指定された構成オプションがあるかどうかを検査する。現在の関数の処理は、検出される構成オプションの影響を受ける。分析エンジンは、分析される各コード・パスごとに、新しい構造メモリ・モデルを構築する。この構造メモリ・モデルを使用して、制御フロー・パスに沿って各文の実行の効果がシミュレートされる。モデル化されたすべてのメモリ位置を追跡する「チャンク・テーブル」と呼ばれるテーブルが設けられる。分析される各コード・パスごとに、コンピュータ・プログラムで使用される変数名をモデル化メモリ内の位置に関連付ける記号テーブルが作成される。
パス内の第1の分を処理する前に、関数の返却値に関するモデル化メモリ位置が作成され、この位置が記号テーブルに挿入される。モデル化メモリ位置は、モデル化中のメモリのアドレス可能な各ユニットあたり1つの記憶値からなる。4バイト・ポインタをモデル化する場合、モデル化メモリ位置は4つの記憶値を含む(1バイトあたり1つの値−最低アドレス可能ユニット)。記憶値は記憶値セットとして収集される。チャンク・テーブルは、すべての記憶値セットを追跡することによってメモリ・モデルを管理する。
メモリ・モデル内に返却値が配置されると、パスに沿って各文が処理される。各文が処理された後、いくつかの異なるコード・パスの間の結果の比較が容易になるように記号テーブルが順序付けされる。パス処理では、リーク検出も実行され、各モデル化メモリ位置が探索され、メモリにおいて、割り付けられているにもかかわらず関数が終了した後にどの記号も指し示さない部分があるかどうかが判定される。検出されたリークについては適切なエラー・メッセージが生成される。パス処理では最後に、メモリ・モデル内のオートモデラ走査構造が、関数の各外部動作モデルに対して実行された試験および各外部動作モデルに加えられた変更を判定する。この情報は、パスに関する結果として要約される。
特定の文の分析では、文がコンピュータ・メモリに与える効果を反映するようにメモリ・モデルを操作する必要がある。分析エンジンは、文処理の開始時に、分析中の文に関してのみ指定された構成オプションがあるかどうかを検査する。現在の文の処理は、検出される構成オプションの影響を受ける。各文は、処理のために適切な文ユニットに分配される。文の各種類ごとに異なる文ユニットがある。一般に、文ユニットは、文中の式を評価し、適切な処理制御結果を再生することによって、プログラム文の実行をシミュレートする。
式のオペランドを表すようにモデル化メモリ位置を作成し、式の演算子をオペランドに適用する効果をシミュレートするようにメモリ・モデルを更新することによって、式が評価される。メモリ・モデルの操作を表す情報が、後でオートモデラによって検査できるようにログされる。演算子を適用する効果のシミュレーションは演算ユニットによって実行される。演算ユニットは、関数を表すのに使用される外部動作モデルと同様な組込みモデルを実行することによって演算をシミュレートする。
文が関数呼出しである場合、被呼関数に対応する外部動作モデルが実行され、この関数呼出しの効果がエミュレートされる。対応する外部動作モデルが存在しない場合、被呼関数が正常にリターンしたという仮定の下にメモリ・モデルが更新される。被呼関数に関してオートモデラによって生成された外部動作モデルを使用して、呼出し関数を分析する際に被呼関数をエミュレートすることができる。
メモリ・モデルで無効な条件が検出された場合、エラー・メッセージが生成される。エラー・メッセージの報告は、構成オプションによって制御される。構成オプションは、ある無効な条件のみを報告することを可能にするか、あるいはある無効な条件の報告を抑制する。さらに、分析エンジンは二重のエラー・メッセージを報告しない。
本発明は、以下の詳細な説明と図面に鑑みてより完全に理解されよう。
【図面の簡単な説明】
第1図は、本発明の一実施形態の入出力のブロック図である。
第2図は、第1図に示した本発明の1つの動作環境のブロック図である。
第3図は、第2図の分析器の内部構造のより詳細なブロック図である。
第4図は、第3図のプリプロセッサのより詳細なブロック図である。
第5図は、Cプログラミング言語文の例と対応する構文解析ツリーの図である。
第6図は、第3図の分析エンジンのより詳細なブロック図である。
第7図は、第6図の関数ごと制御ブロックの機能図のブロック図である。
第8図は、第3図の分析エンジンによって実行される処理を表すブロック図である。
第9図は、本発明の一実施形態で使用されるモデル・テーブル・エントリの図である。
第10図は、第3図の分析エンジンによる処理の開始時に存在する関数呼出し順序付けおよび外部動作関数モデル・インベントリの例の図である。
第11図は、第8図の分析関数ブロックによって実行される処理を表すブロック図である。
第12図は、第11図の分析パス・ブロックによって実行される処理を表すブロック図である。
第13図は、本発明の一実施形態で使用される記号テーブル・エントリの図である。
第14a図は、記号テーブル内の2つのポインタと、第12図の順序記号テーブル・ブロックで使用されるモデル化メモリへのそのリンクの高次表現である。
第14b図は、第12図の順序記号テーブル・ブロックで使用される記号テーブルに第14a図とは逆の順序で配置された第14a図からの2つのポインタ(およびモデル化メモリへのそのリンク)の高次表現である。
第15図は、本発明のメモリ作成ユニットの一実施形態によって実行される処理を表すブロック図である。
第16図は、第15図のメモリ作成ユニットによって使用される原点コンテキスト構造の図である。
第17図は、第15図のメモリ作成ユニットによって使用されるチャンク・データ構造の図である。
第18図は、第15図のメモリ作成ユニットによって使用される記憶値ブロックの図である。
第19図は、第15図のメモリ作成ユニットによって使用される記憶資源ブロックの図である。
第20図は、第15図のメモリ作成ユニットによって作成される各データ構造の間のリンクの高次表現である。
第21図は、第11図の初期設定関数ごとデータ構造ブロックによって使用される実行コンテキストブロックの図である。
第22図は、第12図のパス・ブロックに沿ってプログラム文で実行される処理を表すブロック図である。
第23図は、本発明のブロック・ユニットの一実施形態の論理流れ図である。
第24図は、本発明の式ユニットの一実施形態の論理流れ図である。
第25a図は、第24図のプロセス演算アクション2424で実行される処理の一部を表す論理流れ図である。
第25b図は、第24図の演算処理アクション2424で実行される処理の、第25a図から始まった説明を完了する論理流れ図である。
第26図は、第25b図の演算評価アクション2538によって使用される引数情報ブロックの図である。
第27図は、本発明の演算ユニットの一実施形態の論理流れ図である。
第28図は、本発明のif−elseユニットの一実施形態の論理流れ図である。
第29図は、本発明のループ実行ユニットの一実施形態の論理流れ図である。
第30a図は、本発明の切換えユニットの一実施形態の一部の論理流れ図である。
第30b図は、切換えユニットの第30a図から始まった説明を完了する論理流れ図である。
第31図は、本発明の変数初期設定ユニットの一実施形態の論理流れ図である。
第32図は、本発明のリターン・ユニットの一実施形態の論理流れ図である。
第33図は、本発明のCPH条件選択ユニットの一実施形態の論理流れ図である。
第34図は、本発明の一実施形態で使用されるメモリ・タイプ情報ブロックの図である。
第35図は、本発明の一実施形態で使用される取込み値ブロックの図である。
第36図は、本発明の一実施形態で使用される述語ブロックの図である。
第37図は、本発明のエラー生成ユニットの一実施形態の論理流れ図である。
好ましい実施形態の詳細な説明
本発明の原則によれば、コンピュータ・プログラムの実行をシミュレートし、プログラミング・エラーを検出する方法および装置が提供される。特に、本発明によれば、新規のエラー検出方法は、コンピュータ・プログラムのソース・コードを仮想マシン上の演算のシーケンスにマップする。仮想イメージ、すなわち、分析中のコンピュータ・プログラムによって使用されるメモリの詳細な構造モデル(「メモリ・モデル」と呼ぶこともある)は、仮想マシンの状態を表す。コンピュータ・プログラム中の各変数は、メモリ・モデル内の固有の位置に関連付けされる。各位置は値を含む。各値は、一意に識別され、変数またはその他のプログラム資源の特定の瞬間を表す。実行可能なプログラム命令は、仮想マシンの命令に変換される。仮想マシンは、メモリ・モデルに含まれる値に命令の動作モデルを適用することによって動作する。モデルを適用すると、不正な演算、無効な値、リーク、その他の種類のエラーが検出される。
コンピュータ・プログラムを分析するには、いくつかの異なるコード・パスを通る複数の反復が必要である。個々のコード・パスを通る間、未処理の選択点が処理される。「選択点」とは、条件または述語の値に基づいて、2組以上のプログラム文のうち1つが、実行されるプログラム文として選択されるコンピュータ・プログラム内の点である。プログラムの変数および資源の部分的な知識のみを用いて分析を行うと、条件値または述語値が求められず、選択点が未処理になる可能性がある。
コード・パスに沿った関数呼出しは、関数の外部動作モデルを実行することによって分析される。この外部動作モデルは、対応する関数が入力されたときに真でなければならないものと、対応する関数が終了するときに真になるものを反映する。コンピュータ・プログラムの複数回の反復によって得られた情報は、分析中のプログラムの外部動作モデルを形成するように抽象化される。
以下の説明では、本発明をより完全に理解していただくために、言語構文、プログラム・インタフェース、サンプル・データなど多数の特定の詳細について述べる。しかし、当業者には、これらの特定の詳細なしに本発明を実施できることが明らかになろう。いくつかの場合には、本発明を不必要にわかりにくくしないように周知のデータ・フォーマットおよびデータ構造については詳しく説明しない。
関数レベルの分析
通常、コンピュータ・プログラムは、すでに開発されている構成要素と新たに書かれたコードを組み合わせることによって開発される。本明細書では、「コード」は、ソース・コード、すなわち、人間が理解できる形式のコンピュータ命令および/またはオブジェクト・コード、すなわち、コンピュータが理解できる形式のコンピュータ命令を指す。コンピュータ・プログラムの構成要素は、1つまたは複数の指定されたタスクを実行するコードの部分である。コンピュータ上でコンピュータ・プログラムを実行するときは、ソース・コードが機械コードに変換され、プログラムがロード・モジュールとしてメモリにロードされる。ロード・モジュールの作成とプログラムの実行についての詳細は、Arthur Gill著「Machine and Assembly Language Programming of the PDP−11」(Prentice−Hall,Inc.、1978年)を参照されたい。
コンピュータ・プログラムは任意の数のコンピュータ言語で書くことができる。従来型のコンピュータ言語、すなわち被呼手続き言語では、コンピュータが所与のシーケンス内で実行しなければならない特定の1組の命令をプログラマが記述する。命令とは、プログラミング言語の文であり、コンピュータによって実行される演算と、関連するオペランドのアドレスおよび値を指定する。たとえば、命令A=B+1で、「B」および「1」はオペランドであり、「+」は加算演算を指定するために使用される演算子である。一般に、文は実行すべき動作を指定する。手続きコンピュータ言語の例には、C、Ada、Pascal、Fortran、COBOL、PL/1がある。
C++などいくつかの手続き言語はオブジェクト指向である。オブジェクト指向プログラミング言語は、オブジェクト、すなわち関数および関連するデータの概念的なグループ分けを維持する。オブジェクトは、「クラス」と呼ばれる構成要素に構成される。コンピュータ画面上に表示され、コンピュータ・プログラムを作成するためにコンピュータ・プログラマによってリンクされるグラフィカル画像として命令が表現されるため、いくつかのコンピュータ言語はグラフィックス・ベースである。いくつかのコンピュータ言語は、マサチューセッツ州CambridgeのLotus Development Corporationから市販されているLotus 1−2−3 Spreadsheetプログラム用のLotus 1−2−3マクロ言語など特定のソフトウェア製品に特有の言語である。本発明は、メモリが操作される、任意のコンピュータ言語、すなわち任意のコンピュータ命令プロトコルに適用することができる。
上記ではソース・コード・コンピュータ命令プロトコルについて説明したが、本明細書の教示がオブジェクト・コード形式のコンピュータ命令にも同様に適用できることが理解されよう。本明細書で説明する例示的な実施形態では、分析される特定のコンピュータ言語は周知のCコンピュータ言語である。
Cコンピュータ言語で書かれたコンピュータ・プログラムは通常、いくつかの関数に分割される。関数は、ゼロ個以上のパラメータを入力として受け付け、特定の動作を実行し、多くて1つの戻し項目を出力として生成する。パラメータおよび戻し項目は、メモリに記憶されるデータ構造である。関数は構成要素でも、あるいは構成要素の一部でもよい。本明細書で説明する例示的な実施形態では、コンピュータ・プログラムの各関数が個別に分析される。
コンピュータ・プログラム分析
第1図は、本発明の一実施形態を示す。エラー検出プロセッサ102はコンピュータ・プログラム104を障害インジケータ106およびモデル118に変える。障害インジケータ106は、コンピュータ・プログラム104内の特定のエラーを識別し記述する。本発明の一実施形態では、障害インジケータ106はエラー・メッセージの形をとる。エラー・メッセージについては以下で詳しく説明する。モデル118は、コンピュータ・プログラム104内の対応する関数が実行する入力メモリから出力メモリへのマッピングを定義する。モデル118は、対応する関数の外部可視動作の要約表現であるので外部動作モデルである。コンピュータ関数のモデル化については以下で詳しく説明する。
エラー検出プロセッサ102によるコンピュータ・プログラム104の処理は様々な入力因子の影響を受ける。このような入力因子には、構成ファイル110、コマンド行情報108、ヘッダ・ファイル112、モデル118が含まれる。入力因子については以下で詳しく説明する。
第2図は、エラー検出プロセッサ102用の1つの典型的な動作環境を示す。第2図の実施形態では、エラー検出プロセッサ102は、中央演算処理装置(CPU)204で実行されるアナライザ202を備える。CPU204は、記憶されているプログラム命令を実行する。アナライザ202は、コンピュータ・プログラム104、構成ファイル110、ヘッダ・ファイル112と共にメモリ206に含まれる。メモリ206はさらに、メイン・メモリ(図示せず)と二次記憶域(図示せず)に細分することができる。メイン・メモリはプログラム命令またはデータを保持し、CPU204からメイン・メモリに直接アドレスすることができる。二次記憶域は、直接CPU204の制御を受けることがなく、あるいはCPU204から直接アドレスすることのできないデータを含む。当業者には、メイン・メモリ206に含まれている情報をメイン・メモリに記憶するか、あるいは二次記憶域に記憶し、必要に応じてCPU204で実行できるようにメイン・メモリへ転送することができることが認識されよう。
入出力(I/O)回路208は、データをCPU204へ転送し、CPU204から受け取る責任を負う。CPU204、メモリ206、入出力回路208は、バス210と呼ばれる内部データ・チャネルを通して相互接続される。キーボード212とマウス214は2つの一般的な入力装置であり、CPU204へのデータおよび命令の入力を助けるように構成される。たとえば、通常、コマンド行情報108は、エラー検出プロセッサ102に与えるためにキーボード212を通して入力される。表示装置216とプリンタ218は2つの一般的な出力装置であり、CPU204からのデータの出力を助けるように構成される。第2図の実施形態では、出力信号、すなわち障害インジケータ106はメモリに記憶される。当業者には、表示装置216やプリンタ218など他の出力装置へこの出力信号を送ることもできることが認識されよう。
第3図は、アナライザ202の機能図である。プリプロセッサ302はコンピュータ・プログラム104を対応する構文解析ツリー構造304に変換する。プリプロセッサ302は構文解析ツリー構造304を中間ファイル306に格納する。プリプロセッサ302は、中間ファイル306にも関数分析リスト310、すなわち、コンピュータ・プログラム104に定義されたすべての関数のリストを格納する。コンピュータ・プログラム104に定義されている関数は、分析エンジン308によって分析される関数である。分析エンジン308は、構文解析ツリー構造304を通してエラーを検出し、障害インジケータ106を生成する。分析エンジン308は、コンピュータ・プログラム104の各関数についてのモデル118も生成する。モデル118および分析エンジン308のその他の出力については以下で詳しく説明する。
プリプロセッサ302の機能図を第4図に示す。プリプロセッサ302は構成ファイル110から演算命令を受け取る。構成ファイル110は、ユーザがアナライザ202をカスタマイズすることを可能にする。構成ファイル110に含まれる設定は、コンピュータ・プログラム104が分析される環境の特性を決定する。たとえば、本発明の一実施形態では、構成オプション「maximum_paths」が、各関数について実行される分析の量の限界を設定する。整数オプション値は、アナライザ202によって分析されるパスの数の限界を指定する。本発明の一実施形態に関する構成オプションの完全なリストを付録Bに示す。
構成ファイル110に含まれる構成オプションは構成ファイル・リーダ402によって処理される。構成ファイル・リーダ402は、構成ファイル110から構成オプションを読み込み、構成オプションによって示されたようにパーサ404の演算属性を設定する。パーサ404は、コンピュータ・プログラム104の内部中間表現を作成する。パーサ404はヘッダ・ファイル112を使用してコンピュータ・プログラム104を変換する。一実施形態では、ヘッダ・ファイル112は、「#include」Cプリプロセッサ指令を通してCプログラムによって使用することのできる標準ライブラリ関数を含む。ヘッダ・ファイルは従来技術でよく知られている。ヘッダ・ファイルの詳細な議論については、Mark Williams Companyの「Ansi C:A Lexical Guide」(Prentice Hall 1988年)を参照されたい。
分析の準備として、パーサ404はコンピュータ・プログラム104を解析する。コンピュータ・プログラムを解析すると、コンピュータ・プログラムがより多くの基本サブユニットに分解され、各サブユニットの間の関係が確立されることによって、プログラムの構文構造が判定される。パーサ404は、コンピュータ・プログラム104に現われる文が、ソース言語(C)仕様によって許容されるパターンで生じるかどうかを検査する。バーサ404は、言語仕様に違反する文について障害インジケータ106を生成する。本発明の一実施形態では、障害インジケータ106はエラー・メッセージの形をとる。言語仕様に違反するエラーを「構文エラー」と呼ぶ。
また、他のエラー検出のためにさらに重要なこととして、パーサ404は、コンピュータ・プログラム104の基本サブユニットを構文解析ツリー構造304で表す。構文解析ツリー構造304は構文解析ツリーであり、コンピュータ・プログラム104の構文構造を示す。ツリーとは、多数の分岐を含む階層構造としてグループ化された要素の集合である。ツリーの一番上の要素をルート・ノードと呼ぶ。末端ノード、すなわち分岐のないノードをリーフ・ノードと呼ぶ。ツリー内の残りのノードは内部ノードである。
構文解析ツリーの概念は、例を介して最もよく理解されよう。第5図は、簡単なC文と対応する構文解析ツリーを示す。文502「a=b+1」は2つの式に分解される。一次式は等式であり、「a」を二次式によって生成される値と等しく設定する。一次式の2つのオペランドは「a」と二次式である。二次式は加算演算であり、「b」に1を加える。二次式の2つのオペランドは「b」と「1」である。文502は構文解析ツリー504によって表される。構文解析ツリー504のルート、すなわちルート・ノード506は、等式を表す等式演算子を含む。ルート・ノード506の2つの分岐は、等式の2つのオペランドに至る。リーフ・ノード508はオペランド「a」を含み、内部ノード510は、加算演算を表す加算演算子を含む。内部ノード510の2つの分岐は加算演算のオペランドに至る。リーフ・ノード512は「b」を含み、リーフ・ノード514は「1」を含む。
パーサを使用して、コンピュータ・プログラムを解析すること、構文エラー用のエラー・メッセージを生成すること、構文解析ツリーを構築することはすべて、従来技術でよく知られている。コンピュータ・プログラムの解析に関する詳細な議論については、Alfred V.Aho、Ravi Sethi、Jeffrey D.Ullman著「Compilers: Principles,Techniques,and Tools」(Addison−Wesley Publishing Company、1986年)を参照されたい。
プリプロセッサ302は、構文解析ツリー構造304だけでなく、コンピュータ・プログラム104に定義されたすべての関数のリストも生成する。このリスト、すなわち関数分析リスト310は、構文解析ツリー構造304と共に中間ファイル306に格納される。分析エンジン308は関数分析リスト310にアクセスし、どの関数を分析すべきかを判定する。
第6図は、分析エンジン308の機能図である。主制御ブロック602は分析エンジン308の主入口点である。メイン制御ブロック602は、ユーザによって直接、あるいは統合スクリプトまたは構築ツールによって間接的に、コマンド行から呼び出される。ユーザは、キーボード212またはマウス214を通してコマンドを直接入力することによってアナライザ202を呼び出す。コマンド行に入力されるキー情報、すなわち、コマンド行情報108の一部は(構文解析ツリー構造304を含む)中間ファイル306のリストであり、分析すべきコンピュータ・プログラムに対応する。コマンド行情報108は、構成ファイル110の仕様を含むこともできる。主制御ブロック602は分析エンジン308内の処理の順序を制御する。
初期設定ブロック604は分析エンジン308内の第1の処理を実行する。初期設定ブロック604は、(中間ファイル306のリストと構成ファイル110の任意選択の仕様とを含む)コマンド行情報108とモデル118を処理する。処理が完了すると、制御は主制御ブロック602に戻る。
次に、処理は関数ごと制御ブロック606によって実行される。1つの構文解析ツリー構造304は、1つのコンピュータ・プログラムに対応し、一度に分析される。各構文解析ツリー構造304は、内部に複数の関数を表すことができる。関数ごと制御ブロック606は一度に1つの関数を分析する。関数ごと制御ブロック606は構文解析ツリー構造304をトラバースし、障害インジケータ106を生成する。処理は、分析すべき各構文解析ツリー構造304ごとに繰り返される。すべての構文解析ツリー構造304が分析された後、制御は主制御ブロック602に戻る。
最後の処理は後処理ブロック608によって完了される。後処理ブロック608は、関数ごと制御ブロック606によって分析される関数に対応するモデル118を書き出す。モデル118は任意の出力媒体に書き出すことができる。通常、モデル118は二次記憶域に書き出され、そこで他のコンピュータ・プログラムの分析に使用することができる。後処理ブロック608は制御を主制御ブロック602に返し、分析が終了する。
分析エンジン308によって実行される処理の大部分は、関数ごと制御ブロック606内で行われる。関数ごと制御ブロック606の機能図を第7図に示す。関数ごと制御ブロック606は5つのメイン・オブジェクト上に構築される。オブジェクトとは、機能および関連するデータの概念的なグループである。オブジェクト・ベースの方法を用いて関数ごと制御ブロック606を構成することによって、分析エンジン308の拡張性が高まり、分析エンジン308を保守するのが容易になる。拡張性が高まるのは、他のオブジェクトに影響を及ぼさずに特定のオブジェクト内で機能を追加できるからである。オブジェクトどうしは、慎重に定義されたインタフェースを使用することによって対話する。インタフェースが維持されるかぎり、1つのオブジェクト内の保守が他のオブジェクトに影響を与えることはない。したがって、分析エンジン308全体にわたって大規模な補正を施す必要がある場合と比べて、分析エンジン308を保守し局所補正を実行するのが容易である。
構文解析ツリー・オブジェクト702は、構文解析ツリー構造304によって表されたコンピュータ・プログラム104内の複数のコード・パスをトラバースする。構文解析ツリー・オブジェクト702は、コード・パスを進むにつれて、命令の演算子を対応するオペランドと共に取り込むことによって、コード・パスに沿って命令を処理する。取り込まれた演算子およびオペランドは、シミュレーションのために命令オブジェクト706に渡される。構文解析ツリー・オブジェクト702は、エミュレーションのために関数呼出しも命令オブジェクト706に渡す。命令実行のシミュレーションと関数呼出しのエミュレーションの両方について以下で詳しく説明する。
仮想マシン704は、コンピュータ上のコンピュータ・プログラム104の実行および内部表現をシミュレートする。仮想マシン704は、命令オブジェクト706、仮想メモリ・オブジェクト708、オートモデル・オブジェクト710からなる。命令オブジェクト706は、構文解析ツリー・オブジェクト702から渡された演算子を解釈する。さらに、命令オブジェクト706は、処理中の演算子または関数に対応するモデル118を実行する。モデル118を実行することの効果は、メモリ・モデルが適切に修正されることである。メモリ・モデルについては以下で詳しく説明する。
仮想イメージ・オブジェクト708は仮想イメージ(図示せず)を維持する。仮想イメージとはコンピュータ・メモリの構造モデル(「メモリ・モデル」)である。仮想イメージ・オブジェクト708は、メモリ・モデルの位置、コンピュータ・プログラム104を「実行」する間に各位置にどんな値が記憶されたか、特定のメモリ・モデル位置でどんな試験が実行されたかを追跡する。仮想イメージ・オブジェクト708は、メモリ内の値に作用するvimプリミティブと呼ばれる1組のプリミティブも維持する。コンピュータ・メモリのモデルとvimプリミティブについては以下で詳しく説明する。
オートモデル・オブジェクト710は、現在分析中の関数のモデル118を構築する責任を負う。関数内の各コード・パスが実行された後、オートモデル・オブジェクト710は、仮想イメージ・オブジェクト708に問合せを行い、関数によって実行された入出力マッピングに関する情報を得る。オートモデル・オブジェクト710によって作成されるモデル118は、複数のコード・パスを介して仮想イメージ・オブジェクト708から得られた情報を抽象化したモデルである。モデル118と、それを構築するのに必要な情報については以下で詳しく説明する。
検出される大部分のプログラミング・エラーは仮想イメージ・オブジェクト708で見つけられるが、実際の障害インジケータ106は障害インジケータ・オブジェクト712で生成される。障害インジケータ・オブジェクト712は、プログラミング・エラーを識別する情報を受け取る。本発明の一実施形態では、情報がアセンブルされ、障害インジケータ106はエラー・メッセージの形でユーザに提示される。エラー・メッセージ処理については以下で詳しく説明する。
アナライザの構成
本発明の一実施形態では、アナライザ202のいくつかの異なる構成要素を表すソース・コードは、パッケージと呼ばれるグループにインプリメントされる。パッケージとは、より大きなコンピュータ・プログラムの論理的に関係するサブセットであり、コンピュータ・プログラムに対して関連する1組のサービスを行う。本発明の一実施形態について、表1に、アナライザ202を形成するすべてのパッケージをリストする。
表1の「使用されるパッケージ」のシーケンスは、「パッケージ」のシーケンスにリストされたパッケージからアクセスされる他のパッケージを示す。パッケージは、それがアクセスする他のすべてのパッケージに依存する。したがって、「使用されるパッケージ」のシーケンスは、パッケージ依存性のリストを示す。依存性に留意するのは、パッケージが、依存する他のパッケージの誤動作の悪影響を受ける可能性があるからである。
bot:ユーティリティ・パッケージ
bot、すなわちユーティリティ・パッケージは、文字列、ファイル、ファイル名、メモリ、集合を操作する汎用関数を与える。これらのユーティリティは、他のパッケージが移植性の問題の影響を受けるのを妨げる。第2図の実施形態では、CPU204上でアナライザ202が実行される。異なるCPUを使用した場合、動作環境から与えられる資源が変更されることがある。botパッケージは、他のすべてのパッケージをこのような変更から保護する。さらに、botパッケージ内のユーティリティは、システム資源を使用する必要のあるパッケージに関する一様な呼出し規約を提供する。頻繁に使用される関数に関する一様な呼出し規約を有する場合、アナライザ202の保全性が高まる。botパッケージは他のパッケージには依存しない。
表2は、本発明の一実施形態に含まれるbotパッケージから与えられるユーティリティを参照したものである。
集合
bot_colユーティリティは集合をサポートする。集合とは、概念的には、順序付けされた1組のメンバまたはこれらのメンバの順序付けされたバッグである(すなわち、複製を許可する)。メンバはキーとして使用することができ、その場合、各メンバに何らかの追加のデータを関連付けることができる。
集合は、種類、内容の説明、サイズを有する。種類は、解釈されない整数に過ぎず、予期される種類を実際の種類と比較するために使用される。したがって、集合は明示的に入力され、すなわち、各集合は特定のデータ・クラスを予期する。内容の説明は、集合が何で構成されているか、たとえば、ビット、整数、コピーされた文字列などを指定する。集合のサイズは、集合中のメンバの数である。
本発明の一実施形態では、以下の項目の集合がサポートされる。
・ブール演算
・指し示された文字列(集合が単に、文字列を指し示すポインタを記憶する場合)
・コピーされた文字列(集合が、文字列にメモリを割り付け、この文字列をコピーする場合)
・整数
・ポインタ(集合が、指し示されているものに関する情報を有さない場合)
・バイト(集合が、これらのバイトの構造に関する情報を有さない場合)
アナライザ202での集合の一般的な使用は以下の通りである。
・固定サイズ・ビット・アレイ(抑制コード、選択点履歴)
・名前による参照が重要な可変サイズ文字列リスト(構成オプション)
・記号テーブル:可変サイズであり、解釈されないポインタを指数として有する。
・チャンクおよび取込み値の固定サイズの記憶値
・記憶値のアレイの固定サイズ・サブセット
・(オート・パッケージ内の)パスごと外部テーブル
・述語の集合
・(モデル内の)結果の集合
・(結果内の)外部動作モデルの集合
・モデル・テーブル:可変サイズであり、モデル識別子を指数として有する。
・(mcilによって生成された)関数ポインタの集合
集合は、bot_col_createユーティリティを呼び出し初期サイズおよび最大サイズを供給することによって作成される。初期サイズはゼロ要素でよく、最大サイズは無制限でよい。本発明の一実施形態は、集合サイズが無制限であることを示すためにbot_col_createユーティリティに渡されるBOT_COL_NO_MAX_SIZEと呼ばれる定数を定義する。固定サイズ集合は、初期サイズを最大サイズ値と等しく設定することによって作成される。固定サイズ集合は、最適化されたいくつかの処理系を可能にする。たとえば、固定サイズ・ブール演算集合はビットとしてインプリメントされる。bot_col_copyユーティリティを呼び出して既存の集合をコピーするか、あるいはbot_col_subsetユーティリティを呼び出して既存の集合のサブセットを取り出すことによって、集合を作成することもできる。
集合の各メンバはいくつかの関連する生データを有することができる。メンバに関連する生データを有することは、記号テーブルを集合としてインプリメントする場合に有用である。記号テーブルとは名前の値へのマッピングである。集合としてインプリメントされた記号テーブルは、名前をメンバとして表し、その値を関連する生データとして表す。
本発明の一実施形態では、集合はしばしば、アレイをインプリメントするために使用される。新しいメンバの指数を返すbot_col_add_memberユーティリティを使用することによって、アレイにメンバが追加される。bot_col_get_memberユーティリティを呼び出すことによって、特定の指数にあるメンバがアレイから取り込まれる。bot_col_get_member_and_rawユーティリティによってメンバの値とそれに関連する生データの両方を取り込むことができる。bot_col_replace_memberユーティリティを使用することによってアレイのメンバの値が置き換えられる。
多くの場合、アレイの各メンバを反復する必要がある。アレイの各メンバを通過することは、通常、forループを使用して行われ、当技術分野で十分に理解されている。bot_col_get_num_membersユーティリティはアレイのサイズを返し、このユーティリティを使用してforループの上限を確立することができる。前述のように、forループの本体内部では、bot_col_get_memberを使用してアレイの各メンバを取り込むことができる。
本発明の一実施形態では、参照テーブルは通常、集合としてインプリメントされる。bot_col_lookup_memberユーティリティを使用して、メンバの指数を特定の値と共に返すことができる。参照テーブルは、入力値と出力値との間の対応を識別する。参照テーブルは従来の技術で十分に理解されている。
分析エンジン308の詳細な説明
前述のように、分析エンジン308は、障害インジケータ106およびモデル118を生成するためにユーザによってコマンド行から(あるいは自動化ツールによって間接的に)呼び出される。本発明の一実施形態によれば、分析エンジン308の処理はブロック図800(第8図)で示されている。処理はベース・パッケージアクション802(以下では「アクション802」と呼ぶ)のグローバル・データ構造初期設定から始まり、この場合、4つのベース・パッケージによって必要とされるグローバル・データ構造が初期設定される。4つのベース・パッケージとはbotパッケージ、errパッケージ、ctxパッケージ、confパッケージである。アクション802は、コンピュータ・プログラム104を処理するために分析エンジン308によって必要とされるセットアップを実行する。
すべてのパッケージは、botパッケージから与えられるユーティリティを使用する。したがって、botパッケージによって必要とされるグローバル・データ構造がまず初期設定される。初期設定の後で、botパッケージ内のユーティリティを他のパッケージが使用することができる。次に、構成オプションを処理する際に出会うエラーを処理するためにerrパッケージを使用できるようにerrパッケージ内のグローバル・データ構造が初期設定される。errパッケージ処理の後で、実行コンテキストブロック2100、すなわちctxパッケージによって定義されるグローバル・データ構造が割り付けされクリアされる。errパッケージは、エラー・メッセージに挿入されるコンテキスト情報に関して実行コンテキストブロック2100を参照する。実行コンテキストブロック2100については以下で詳しく説明する。実行コンテキストブロック2100が初期設定された後、confパッケージのグローバル・データ構造が初期設定される。第8図の実施形態では、botパッケージ、errパッケージ、ctxパッケージ、confパッケージのグローバル・データ構造の初期設定はルーチンによって実行される。マイクロフィッシュの付録Aの実施形態では、botパッケージ、errパッケージ、ctxパッケージ、confパッケージのグローバル・データ構造を初期設定するルーチンをそれぞれ、bot_begin、err_begin、ctx_begin、conf_beginと呼ぶ。処理はアクション802からデフォルト構成ファイル処理アクション804(以下では「アクション804」と呼ぶ)へ移る。
構成オプションは、分析エンジン308によって実行される多くの処理に影響を与える。したがって、アクション802で必要なセットアップが行われると、アクション804で構成オプションが処理される。構成オプションは構成ファイル110内に記憶される。デフォルト構成ファイル110はデフォルト・オプション設定を含む。デフォルト構成ファイル110は分析エンジン308用の標準構成を生成する。
デフォルト構成ファイル110はアクション804内で処理される。まず、デフォルト構成ファイルが見つけられる。本発明の一実施形態では、デフォルト構成ファイルはアナライザ202のホーム・ディレクトリに格納される。デフォルト構成ファイル110が見つかった後、分析エンジン308にデジタル・オプション設定がロードされる。デフォルト構成ファイルに含まれるすべてのオプションがロードされるまで、オプション設定が一度に1つずつ読み込まれる。第8図の実施形態では、デフォルト構成ファイル110はルーチンによって処理される。マイクロフィッシュの付録Aの実施形態では、conf_load_defaultsルーチンによってアクション804が実行され、このルーチンはconf_read_fileルーチンをすべてのオプションを読み込む。conf_read_fileルーチンは、構成ファイル110全体にわたって1行ずつ反復し、conf_parse_optionルーチンを使用して構成ファイルの各行を解析し、オプションを取り込む。アクション804によって実行される関数は当業者によく知られている。
構成オプションは、分析エンジン308によって実行される分析のレベルと、分析エンジン308によって生成される出力の種類および量を制御する。たとえば、構成オプションは、処理中のコードで実行されるパスの数と、どんなエラーが報告されるかと、エラーが報告される形式と、あるエラーが報告される場所を判定することができる。第8図の実施形態については、構成オプションのリストおよび各オプションの説明はアペンデッィクスBに含まれている。
処理は、アクション804からユーザ指定構成情報処理アクション806(以下では「アクション806」と呼ぶ)に移り、ユーザ指定構成ファイル110が処理される。ユーザは、コマンド行情報108内のコマンド行上に構成ファイル110を指定することによって分析エンジン308内で実行される処理をカスタマイズするオプションを有する。ユーザ指定構成ファイル110に設定された構成オプションは、デフォルト構成ファイル110に設定された対応するオプションに優先する。
本発明の一実施形態では、コマンド行上の「−config」制御語を使用してオプションのユーザ指定構成ファイル110が識別される。「−config」制御語の後に空白が続き、その後にユーザ指定構成ファイル110の名前が続く。たとえば、「−config custom」は、「custom」と呼ばれるユーザ指定構成ファイル110を識別する。
アクション806はまず、ユーザがオプションの構成ファイル110を指定したかどうかを判定する。そうでない場合、アクション806ではもはや処理は必要とされない。ユーザ指定構成ファイル110が識別された場合、処理はアクション804と同様に継続する。アクション806内では、ユーザ指定オプション設定が分析エンジン308にロードされる。このようなユーザ指定オプション設定は、アクション804に設定された対応するデフォルト設定に優先する。ユーザ指定構成ファイル110に含まれるすべてのオプションがロードされるまで、オプション設定は一度に1つずつ読み込まれる。第8図の実施形態では、ユーザ指定構成ファイル110はルーチンによって処理される。マイクロフィッシュの付録Aの実施形態では、アクション806はconf_loadルーチンによって実行され、このルーチンは、conf_load_defaultsルーチンと同様に、conf_read_fileルーチンを使用してすべてのオプションを読み込む。
アクション806は、ユーザによって指定されたコマンド行構成オプションも処理する。コマンド行情報108内のコマンド行上に複数の構成オプションを指定することができる。本発明の一実施形態では、制御行構成オプション(およびその値)の前に「−prefix_opt」制御語が指定される。「−prefix_opt」制御語の後で、引用符で囲まれた構成オプションに値が割り当てられる。言い換えれば、コマンド行構成オプション指定は以下の形式を有する。
−prefix_opt“option name=option value”
たとえば、「maximum_paths」構成オプションは、以下のものを指定することによってコマンド行上に設定することができる。
−prefix_opt“maximum_paths=300”
付録Bは、本発明の一実施形態についての様々な構成オプションおよび許容されるオプション値を含む。
アクション806は、コマンド行構成オプションをコマンド行上のその位置に対して左から右へ処理する。構成オプションがコマンド行上に指定されたか、それとも構成ファイル110内に含まれるかにかかわらず、所与のコマンド行構成オプション指定は、すでに指定されているすべての構成オプションに優先する。
処理はアクション806から残余グローバル・データ構造初期設定アクション808(以下では「アクション808」と呼ぶ)へ移り、コンピュータ・プログラム104を分析する準備として残りのパッケージが初期設定される。構成オプションをロードした後の、処理を行う方法は知られている。この時点で、処理に必要とされるグローバル・データ構造が初期設定される。本発明の一実施形態では、autoパッケージ、cphパッケージ、exeパッケージ、insパッケージ、mcilパッケージ、symパッケージ、vimパッケージはすべて、グローバル・データ構造を有し、これらの構造を初期設定しなければならない。第8図の実施形態では、ルーチンを使用してパッケージ内のグローバル・データ構造が初期設定される。マイクロフィッシュの付録Aの実施形態では、「pkg_begin」と呼ばれるルーチンによってパッケージ内のグローバル・データ構造が初期設定される。「pkg」はパッケージの名前を表す。たとえば、autoパッケージ内のグローバル・データ構造は、「auto_begin」と呼ばれるルーチンによって初期設定される。
処理はアクション808から中間ファイル読取りアクション810(以下では「アクション810」と呼ぶ)へ移り、コマンド行情報108内のコマンド行上にリストされた中間ファイル306が読み取られ、準備処理が実行される。まず、コマンド行に含まれる中間ファイル306のリストが取り込まれる。各中間ファイル306の内容がメモリに読み込まれる。ユーザは、空白で区切られた複数の中間ファイル306をコマンド行上に指定することができる。
プリプロセッサ302は、構築されたあらゆる中間ファイル306に関数分析リスト310を挿入する。関数分析リスト310は、対応する中間ファイル306内の分析すべきすべての関数を含む(すなわち、構文解析ツリー構造304によって表されたプログラムによって定義されたすべての関数のリスト)。分析すべきすべての関数を識別する関数分析マスタ・リストを形成するために、コマンド行上に指定されたすべての中間ファイル306から得たすべての関数分析リスト310の複合リストが作成される。
分析を必要とするすべての関数の名前が判明した後、処理では続いて、すべての被呼関数の名前が判定される。「被呼関数」は、(通常は一時的に)転送される実行の制御である関数を示す。関数分析マスタ・リストを巡回することによってすべての被呼関数のリストが生成される。分析を必要とする各関数について、対応する構文解析ツリー構造304がトラバースされ、呼び出される関数が調べられる。アクション810は、すべての被呼関数の名前と関数呼出しの順序の両方を判定する。
分析エンジン308は、被呼関数の実行をエミュレートする。分析エンジン308は、対応するモデル118を実行できる場合、被呼関数のより確実なエミュレーションを実行することができる。そうでない場合、分析エンジン308は、通常実行される被呼関数を示すことからなる最低限のエミュレーションを実行する。
すべての被呼関数の名前を収集した後、これらの関数に関して存在するすべてのモデルを収集することが可能である。アクション810内で生成される関数呼出しの順序によって、分析エンジン308は、プログラム全体がより完全に調べられるように関数分析の順序付けを調整することができる。分析エンジン308はできる限り、関数を分析の他の部分でエミュレートすることが必要になる前にその関数を分析しモデル化する。関数分析の適切な順序は、アクション810の最後に関数呼出し順序付け情報のトポロジカル・ソートを行うことによって決定される。トポロジカル・ソートによって、順序付けされた関数呼出しのリストが生成される。関数は、順序付けされた関数呼出しのリストに示された順序で処理される。トポロジカル・ソートは当技術分野でよく理解されている。
例1は、第10図に示されており、関数呼出し順序付けの例を示す。第10図を参照するとわかるように、関数F1 1002は関数F2 1004を呼び出す。関数F2 1004は関数F3 1006およびF4 1008を呼び出す。この例では、関数f1 1002、f2 1004、f3 1006は関数分析マスタ・リスト上にある(すなわち、分析を必要とする)。被呼関数のリストにはf2 1004、f3 1004、f4 1008が含まれる。これらの関数のうちで、分析の開始時に存在するのは関数f4 1008のモデル、f4モデル1010だけである。したがって、f4モデル1010が実行され、関数f4 1008の呼出しがエミュレートされる。関数呼出し順序付けでは、分析の開始時にどのモデルが存在するかだけでなく、どの関数を最初に分析するかも決定される。f2 1004のモデルが構築される前にまずf1 1002を分析すると、f2 1004の最低限のエミュレーションが行われる。f2 1004を最初に分析しモデル化した場合は、関数f1 1002をより詳しく分析することができる。同様な理由で、f2 1004を分析する前にf3 1006が分析されモデル化される。f3 1006が分析されモデル化された後、f2 1004のより完全な分析が可能になり、最終的にf1 1002がより良好に分析される。
処理はアクション810からモデル・テーブル構築アクション812(以下では「アクション812」と呼ぶ)へ移り、モデル・テーブルが構築される。モデル・テーブルとは、モデル・テーブル・エントリ900を指し示すポインタの集合である。各モデル・テーブル・エントリ900は、被呼関数リスト上の被呼関数に対応する。モデル・テーブル・エントリ900を第9図に示す。モデル・テーブル・エントリ900は、「function name(関数名)」902、「model pointer(モデル・ポインタ)」904、「model source(モデル・ソース)」906、「output destination(出力宛先)」908、「newer model index(新しいモデル・インデックス)」910、「loaded flag(ロード済みフラグ)」912、「missing flag(欠落フラグ)」914、「report missing flag(欠落報告フラグ)」916、「automodel flag(オートモデル・フラグ)」918、「newer model flag(新しいモデル・フラグ)」920、「written flag(書込み済みフラグ)」922、「replace flag(置換えフラグ)」924、「queue for write flag(書込み待ち行列フラグ)」926の各フィールドを含む。
フィールド「function name」902は、モデル・テーブル・エントリ900に関連付けされた関数の識別子を指定する。フィールド「model pointer」904は、モデル・テーブル・エントリ900によって表されるモデル118を指し示す。フィールド「model source」906は、「model pointer」904によって指し示されたモデルがどこから読み取られたかを指定する。フィールド「ouput destination」908は、「model pointer」904によって指し示されたモデルを書きこむファイルを指し示す。フィールド「newer model index」910は、このモデル・テーブル・エントリ900が関連付けされているのと同じ関数のモデルのより新しいバージョンを指し示すモデル・テーブル内のエントリのインデックスを指定する。
「loaded flag」912は、このテーブル・エントリに関してモデルがロードされているかどうかを示す。「missing flag」914は、このテーブル・エントリに特殊な「missing model」が割り当てられているかどうかを示す。「report missing flag」916は、このテーブル・エントリに関して「missing model」メッセージが発行されているかどうかを示す。「automodel flag」918は、「model pointer」904によって指し示されたモデルが、現在の分析中にオートモデラによって作成された場合には真である。「automodel flag」918は、モデルが最初に、現在のコンテキストのコンテキスト外でオートモデラによって作成された場合でも偽である。「newer model flag」920は、このモデル・テーブル・エントリ900が関連付けされているのと同じ関数の、オートモデラによって生成されたモデル118を表すモデル・テーブル・エントリ900をオートモデラが追加しているかどうかを示す。「written flag」922は、モデルがファイルに書き出されたかどうかを示す。「replace flag」924は、「model pointer」904によって指し示されているモデル118をオートモデラが置き換えているかどうかを示す。最後に、「queue for write flag」は、分析の終了時にモデルに書き出すべきである場合は真である。そうでない場合は偽である。
まず、アクション812内で、モデル・テーブルを具体化する集合が作成される。モデル・テーブルはテーブル・エントリ900をモデル化する1組のポインタであるので、ポインタの集合が作成される。モデル・テーブルの集合が作成されると、テーブル内にエントリはなくなる。次に、モデル・テーブル内の初期エントリが作成される。すなわち、モデル・テーブル・エントリ900を指し示すメンバがモデル・テーブル集合に追加される。本発明の一実施形態では、モデル・テーブル集合はルーチンによって構築される。マイクロフィッシュの付録Aの実施形態では、ルーチンins_mt_readがモデル・テーブルの構築を制御し、bot_col_create_collectionユーティリティ・ルーチンを呼び出してモデル・テーブル集合を作成する。
アクション812は次に、モデル・テーブルによって指し示された初期モデル・テーブル・エントリを作成する。アクション812は、アクション810内で構築された被呼関数のリスト上の各関数を巡回する。このリスト上の各関数について、モデル・テーブル・エントリ900が割り付けられ初期設定される。フィールド「function name」902は現在の被呼関数の名前に設定される。次いで、モデル・テーブル・エントリ900は、フィールド「missing flag」914を真に設定することによって欠落モデルを示すように設定される。モデル・テーブル集合にメンバを追加することによって、新たに作成されたモデル・テーブル・エントリを指し示すポインタがモデル・テーブルに挿入される。また、オートモデラによって生成されたモデル118で欠落モデルを置き換えるべきであることを示すフラグ「replace flag」924がオンにされる。このように、処理は被呼関数リスト全体にわたって反復される。したがって、アクション812が完了した後、被呼関数リスト上のあらゆる関数に関するモデル・テーブルによって指し示される1つのモデル・テーブル・エントリ900がある。本発明の一実施形態では、モデル・テーブルはルーチンを通して初期設定される。マイクロフィッシュの付録Aの実施形態では、ルーチンmcil_get_next_model_to_readは被呼関数名のリスト全体にわたって反復され、ルーチンins_mt_insertはモデル・テーブル・エントリ900を作成し、このエントリを欠落モデルを示すように初期設定し、bot_col_add_memberユーティリティ・ルーチンはモデル・テーブル集合にメンバを追加するために使用される。処理はアクション812から集合モデル化アクション814(以下では「アクション814」と呼ぶ)へ移る。
アクション814は、モデル・テーブルで参照された各モデル・テーブル・エントリ900に対応するすでに構築されているモデル118(すなわち、被呼関数リスト上のすべての関数のモデル)を収集する。利用可能なモデル118を探索する第1のステップは、モデル・ファイルを探索する位置のリストを構築することである。モデル・ファイルとはモデルを含むファイルであり、規約上、ファイル拡張識別子を区別することによってモデル・ファイルが認識される。たとえば、「mod」と「mar」は、モデル・ファイルを識別する2つの拡張子である。「mod」拡張子は現在のモデル118を含むモデル・ファイルを示し、「mar」拡張子は、保存されているモデル118を含むモデル・ファイルを示す。単一のモデル・ファイルに複数のモデル118を格納することができる。モデル・ファイルは、ファイルにどの関数がモデル化されているかを示すインデックス情報をファイルの開始位置と終了位置に有することができる。
通常、モデル・ファイルはディレクトリに配置され、ファイルを探索する場所のリストは1組のディレクトリである。組内の各ディレクトリは、モデル・ファイルを求めて探索される。適切なファイル拡張子を有するすべてのファイルが処理される。選択された各ファイルについて、モデル・ファイルが割り付けされ開かれる。モデル・ファイルを開いた後、インデックスが走査され、ファイル内のモデル118のうちで、分析に必要な関数に対応するモデルがあるかどうかが判定される。これは、モデル・ファイル・インデックス中の関数名を被呼関数リスト上の名前と比較することによって行われる。名前が一致するたびに、一致した関数を表すモデル・テーブル・エントリ900内で「loaded flag」912が真に設定されていないかぎり、対応するモデル118が解析されメモリにコピーされる。コピーされたモデル118を指し示すポインタは、フィールド「model pointer」904にある対応するモデル・テーブル・エントリ900に入力される。このモデル・テーブル・エントリ900に関する「missing flag」はオフにされる。また、この同じモデル・テーブル・エントリ900について、「loaded flag」912が真に設定され、「replace flag」924が偽に設定される。「loaded flag」912が真に設定されたときは、アクション814が、モデル・テーブル・エントリ900によって表された関数に一致するすべての後続のモデル118を無視すべきであることを意味する。すべての一致が処理されると、選択されたモデル・ファイルの処理が完了し、モデル・ファイルが閉じられ割付け解除される。モデル118については以下で詳しく説明する。本発明の一実施形態では、アクション814はあるルーチンによって実行される。マイクロフィッシュの付録Aの実施形態では、ルーチンins_mt_readが、すでに構築されているモデル118を見つけ、ルーチンins_mt_parseがモデル・ファイル内のモデルを解析する。
アクション814は、ファイルのリスト、すなわち出力モデル・ファイル・リストも生成する。このリストは、分析中に構築されたモデル118の出力宛先を指定する。出力モデル・ファイル・リストは、モデル118がモデル・テーブル・エントリ900に挿入されるときに動的に構築される。モデル118がモデル・テーブル・エントリ900にリンクされると、出力モデル・ファイル・リストが検査され、モデル118によって表される関数のソース中間ファイル306と同じファイル名と「mod」のファイル拡張子とを有する対応する出力モデル・ファイルがあるかどうかが調べられる。探している出力モデル・ファイルが見つからない場合、このファイルは出力モデル・ファイル・リストに追加される。ある関数を表すように構築されたモデル118は、最初にその関数を定義した中間ファイルに対応する出力モデル・ファイルに格納される。たとえば、中間ファイル「test.il」が関数f1を含む場合、関数f1を表すように構築されたモデル118は出力モデル・ファイル「test.mod」に格納される。アクション814がモデル・テーブル・エントリ900を初期設定すると、フィールド「output destination」908が、フィールド「function name」902で識別された関数を含む中間ファイル306に対応する出力モデル・ファイルの名前を記録するように設定される。モデル・ファイルについては以下で詳しく説明する。処理はアクション814から関数分析アクション816(以下では「アクション816」と呼ぶ)へ移る。
アクション816は、関数分析マスタ・リスト上のすべての関数を分析する。処理の順序は、順序付き関数呼出しリストによって制御される。関数は、順序付き関数呼出しリスト上の第1の関数から最後の関数まで順次分析される。各関数について、対応する構文解析ツリー構造304がメモリに読み込まれる。関数を分析すると、障害インジケータ106(エラーが検出された場合)と、分析された関数を表すモデル118が生成される。関数の分析が完了すると、メモリに読み込まれた構文解析ツリー構造304は破棄される。このように、必要に応じてのみ構文解析ツリー構造304を記憶することによって、CPU204のメモリ資源が節約される。アクション816で実行される関数ごと処理については以下で詳しく説明する。処理は、アクション816から出力モデルアクション818(以下では「アクション818」と呼ぶ)へ移る。
アクション818は、アクション816によって作成されたモデル118を記憶する責任を負う。出力モデル・ファイル・リスト内の各出力モデル・ファイルは順次処理される。まず、モデル出力ファイルが作成され、割り付けられ、開かれる。次に、アクション818が、モデル・テーブル全体にわたって反復され、各モデル・テーブル・エントリ900に問合せを行う。フィールド「output destination」908が現在のモデル出力ファイルの名前に等しく、フラグ「queue for write flag」926が真である場合、フィールド「model pointer」904によって指し示されたモデル118が現在のモデル出力ファイルに格納される。「written flag」922は真に設定される。
出力モデル・ファイル・リスト内の最後のファイルに対する処理が完了すると、制御はグローバル・データ構造除去アクション820(以下では「アクション820」と呼ぶ)へ移る。
処理はアクション820で終了し、記憶域クリーンナップが行われる。第8図の実施形態では、あるルーチンを使用して、パッケージ内のグローバル・データ構造が除去またはクリーンナップされる。マイクロフィッシュの付録Aの実施形態では、「pkg_end」と呼ばれるルーチンを実行することによって、パッケージ内のグローバル・データ構造が除去またはクリーンアップされる。「pkg」はパッケージの名前を表す。たとえば、errパッケージ内のグローバル・データ構造は、「err_end」と呼ばれるルーチンによってクリーンナップされる。bot、err、conf、auto、cph、ctx、exe、ins、mcil、sym、vimの各パッケージには「pkg_end」ルーチンが実行される。この時点で、コンピュータ・プログラム104の処理が完了する。
関数分析
前述のように、関数分析マスタ・リスト上にリストされた関数の分析はアクション816で行われる。(アクション810で実行されるトポロジカル・ソートによって作成される)順序付き関数呼出しリストは、関数が分析される順序を制御する。アクション816は、ブロック図1100(第11図)に示したように、順序付き関数呼出しリストを巡回し、リスト上の各関数について関数ごと処理を実行する。分析中の関数は現在の関数として指定される。関数ごと処理は、関数ごとデータ構造初期設定アクション1102(以下では「アクション1102」と呼ぶ)から始まる。
アクション1102は、関数ごとに使用されるデータ構造を割り付けるか、あるいは初期設定する。第11図の実施形態では、あるルーチンを使用することによって、パッケージ内の関数ごとデータ構造を割り付けるか、あるいは初期設定する。マイクロフィッシュの付録Aの実施形態では、「pkg_begin_function」(「pkg」はパッケージの名前を表す)と呼ばれるルーチンが、パッケージ内の関数ごとデータ構造を割り付けるか、あるいは初期設定する。たとえば、exeパッケージ内の関数ごとデータ構造は、「exe_begin_function」と呼ばれるルーチンによって割り付けられる。「pkg_begin_function」ルーチンは、ctx、mcil、err、vim、sym、ins、cph、auto、exeのパッケージ順序で呼び出される。
アクション1102は、実行コンテキストブロック2100に情報をポストする。実行コンテキストブロック2100を第21図に示す。実行コンテキストブロック2100には、「filename(ファイル名)」2102、「function name(関数名)」2104、「current function(現在の関数)」2106、「current iteration(現在の反復)」2108、「current statement(現在の文)」2110、「current line number(現在の行番号)」2112、「current expression(現在の式)」2114、「emulation depth(エミュレーション深さ)」2116、「emulation context list(エミュレーションコンテキストリスト)」2118の各フィールドが含まれる。
フィールド「filename」2102は、現在の関数を含むソース・ファイルを識別する。フィールド「function name」2104は、現在の関数を識別する。フィールド「current function」2106は、現在の関数を一意に識別する、現在処理されている構文解析ツリー構造304内のノードを指し示すポインタである。フィールド「current iteration」2108は、分析された現在の関数中のパスの数のカウントを指す。フィールド「current statement」2110は、現在分析されている文を識別する、現在処理されている構文解析ツリー構造304内のノードを指し示すポインタである。フィールド「current line number」2112は、現在分析されている文を含むフィールド「filename」2102のソース・ファイル内の行を識別する。フィールド「current expression」2114は、現在分析されている式を識別する、現在処理されている構文解析ツリー構造304内のノードを指し示すポインタである。フィールド「emulation depth」2116は、フィールド「function name」2114内の関数の入れ子にされた関数呼出しの深さである。フィールド「emulation context list」2118は、入れ子にされた関数呼出しで呼び出される各関数に関するコンテキスト情報の集合である。関数呼出しが「入れ子にされる」のは、その関数呼出しが他の関数呼出しの引数として使用されるか、あるいはそれ自体の引数の1つとして他の関数呼出しを使用するときである。フィールド「emulation depth」2116および「emulation context list」2118が意味を持つのは、現在分析されている式が関数呼出しであるときだけである。
アクション1102は、「filename」2102、「function name」2104、「current function」2106を設定する。本発明の一実施形態では、あるルーチンを使用して、実行コンテキストブロック2100の最初の3つのフィールドが初期設定される。マイクロフィッシュの付録Aの実施形態では、「ctx_begin_function」と呼ばれるルーチンが実行コンテキストブロック2100の最初の3つのフィールドを初期設定する。関数ごとデータ構造が割り付けられるか、あるいは初期設定され、グローバル・データ構造が関数レベル情報で更新された後、処理は構文解析ツリー構造ロードアクション1104へ移る(以下では「アクション1104」と呼ぶ)。
アクション1104は、現在の関数を表す構文解析ツリー構造304をメモリに読み込む。処理は、アクション1104からパス分析アクション1108(以下では「アクション1108」と呼ぶ)へ移る。
アクション1108は、現在の関数全体にわたる複数のコード・パスをシミュレートされた実行を追跡することによって現在の関数を分析する。アクション1108は、最大パス数に達するか(maximum_pathオプションが設定されている場合)、あるいはもはや実行するコードがなくなるまで、コード・パスを実行し続ける。maximum_pathオプションは、ユーザが、各関数に対して実行される分析の量の限界を設定することを可能にする。maximum_pathオプションを設定すると、(現在の関数内のいくつかのコード・パスがトラバースされていない場合でも)分析されるパスの数の上限が設定される。アクション1108は、最初に実行すべきパスを見つけるループを実行し、次いでこのパスを実行する。
アクション1108は、決定的選択点履歴を使用してパスを見つける。関数の実行は、選択点ノードと選択エッジからなる選択点履歴(CPH)ツリーとしてモデル化される。CPHツリーは、第5図に示した構文解析ツリーと同様に構造のツリーである。CPHツリーのルート・ノードは、現在の関数中の第1の未処理の選択点であり、リーフ・ノードは関数リターンおよび関数終了である。前述のように、選択点とは、条件または述語の値に基づいて2組以上の代替プログラム文のうちの1組の間で選択が行われるプログラム内の点である。選択点ノードは、分析エンジン308が、処理するのに十分な情報を有さない選択点に対応する。選択点ノードは、現在の関数内の未処理の選択点に対応する構文解析ツリー構造304内のノードを指し示すポインタを含む。選択エッジは、選択点のいくつかの異なる可能な処理に対応する。たとえば、相等性に関する試験では真と偽のどちらかが判定される。選択点ノードは相等性試験に対応する。この特定の選択点ノードは2つの選択エッジを有する。一方の選択エッジは「真」結果に対応し、一方は「偽」結果に対応する。
選択点履歴は、各パスが複製可能であるという点で決定性である。コードのいくつかの異なる実行において未処理の各選択点を同様に処理する場合、コード内の同じパスをたどる。各選択点ノードは、固定数の選択エッジを有する。これは、未処理の選択点ノードから延びるパスの数が固定されることを意味する。この数は、実行の前には未知であるが、選択点ノードに関する選択を初めて行うときに決定される。現在の関数を実行する前にはCPHツリー構造全体が未知である。CPHツリーは、現在の関数を分析する間に動的に構築される。
CPHツリーは、修正幅優先構築方法を使用したプログラム実行中に構築される。アクション1108は「現在レベル」値を維持する。現在レベル値は、CPHツリーにどの選択点が追加されたかを示す。任意の所与の時間には、現在のレベルよりも1つ以上上のレベルであるCPHツリーのすべてのノードが処理されている。したがって、これらのノードのすべての選択エッジが決定される。
アクション1108は、現在のレベルよりも1つ上のレベルであるノードから出てルート・ノードに戻る未処理の選択エッジを無作為に選択することによって、新しいパスを選択する。このように、アクション1108は、ルート・ノードから始まるパスを決定し、現在のレベルよりも1つ上のレベルの選択されたノードまでCPUツリーをトラバースする。現在のレベルよりも1つ上のレベルのノードから出る未処理の選択エッジが見つからない場合、現在レベル値が1だけ増加され、ステップが繰り返される。現在レベル値を増加させることは、分析がCPHツリー内で1レベル下に移動したことを意味する。現在レベル値が増加され、現在のレベルよりも1つ上のレベルのノードから出る未処理の選択エッジが依然としてない場合、もはやパスを見つけることはできない。本発明の一実施形態では、あるルーチンによって新しいパスが決定される。マイクロフィッシュの付録Aの実施形態では、「cph_path_find」ルーチンが新しいパスを決定する。
各パスが決定されるたびに、アクション1108はメモリ・モデルを作成し、コード・パスに沿った命令のメモリ・モデルに対する効果をシミュレートし、コード・パス上の関数呼出しをエミュレートし、エラーを検出した時点で障害インジケータ106を生成し、現在の関数のモデル118を構築するのに必要な情報を収集する。このパスごと処理については以下で詳しく説明する。処理はアクション1108から関数外部動作モデル収集アクション1110(以下では「アクション1110」と呼ぶ)へ移る。
アクション1110は、将来モデル作成時に使用される現在の関数の外部動作モデルを収集する。アクション1110は、収集した外部動作モデルをグローバル変数に変換する。以後の処理時に、モデル作成ルーチンがグローバル変数からこのような外部動作モデルを抽出する。関数外部動作モデルとは、関数の外部で参照することができるか、あるいはいくつかの関数呼出しにわたって持続する値、すなわち局所静的変数を有する関数内のオブジェクトである。関数外部動作モデルの最も一般的な2つの例はパラメータと返却値である。現在の関数の外部動作モデルが記録された後、処理はアクション1110から構文解析ツリー構造解放アクション1112(以下では「アクション1112」と呼ぶ)へ移る。
アクション1112は、現在の関数を表す構文解析ツリー構造304を解放する。現在の関数を表す構文解析ツリー構造304を必要なくなった時点で解放することによって、メモリ資源を効率的に使用することができる。本発明の一実施形態では、アクション1112はあるルーチンによって実行される。マイクロフィッシュの付録Aの実施形態では、ルーチン「mcil_release_memory_region」が構文解析ツリー構造304を解放する。処理はアクション1112から関数ごとデータ構造クリーンナップアクション1114(以下では「アクション1114」と呼ぶ)へ移る。
関数ごと処理はアクション1114で終了し、関数ごとに使用される記憶域がクリーンナップされる。本発明の一実施形態では、ルーチンを使用して、パッケージ内の関数ごとデータ構造が解放またはクリーンナップされる。このルーチンは、exe、auto、cph、ins、sym、vim、err、mcil、exeのパッケージ順で呼び出される。特に、それぞれのautoパッケージ・ルーチンは現在の関数のモデル118を作成する。オートモデル化については以下で詳しく説明する。マイクロフィッシュの付録Aの実施形態では、「pkg_end_function」(「pkg」はパッケージの名前を表す)というラベルの付いたルーチンが、関数ごとに使用される記憶域をクリーンナップまたは解放する。たとえば、vimパッケージ内の関数ごとデータ構造は、「vim_end_function」というラベルの付いたルーチンによって解放される。「pkg_end_function」ルーチンは、「pkg_begin_function」ルーチンの逆の順序で呼び出される。アクション1114が完了すると、関数ごと処理が終了する。
パスの分析
前述のように、アクション1108は、複数のシミュレートされた実行のコード・パスを追跡することによって現在の関数を分析する。アクション1108は、分析する各パスごとに1回ずつ、現在の関数を表す構文解析ツリー構造304(以下では、「現在の構文解析ツリー構造304」と呼ぶ)をトラバースする。アクション1108は、分析する各パスについて、ブロック図1200(第12図)に示したようにパスごと処理を実行する。分析中のパスは現在のパスとして指定される。パスごと処理は、プログラム読取りアクション1202(以下では「アクション1202」と呼ぶ)から始まる。
アクション1202は、現在の関数に関してプラグマが定義されているかどうかを判定する。プラグマとはIntrinsa指令であり、プラグマの直後の関数または文の制御を設定する。ユーザは、関数のソース・コードにIntrinsaプラグマを埋め込むことによって構成オプションを指定することができる。関数の直前に配置されたプラグマは、関数全体に適用される。たとえば、以下のプラグマは、主関数のすべての文に適用される。
「抑制(suppress)」構成オプションの詳細は、付録Bに記載されている。
アクション1202は、プラグマを見つけるとまず、プラグマによって指定された構成オプションの現在の設定を保存し、次いでプラグマに指定された値に応じてこのような構成オプションを設定する。処理はアクション1202からパスごとデータ構造初期設定アクション1204(以下では「アクション1204」と呼ぶ)へ移る。
アクション1204は、パスごとに使用されるデータ構造を割り付けるか、あるいは初期設定する。第12図の実施形態では、あるルーチンを実行することによって、パッケージ内のパスごとデータ構造が割り付けられるか、あるいは初期設定される。このようなルーチンは、ctx、mcil、err、vim、sym、ins、cph、auto、exeのパッケージ順で呼び出される。マイクロフィッシュの付録Aの実施形態では、アクション1204で実行されるルーチンには「pkg_begin_path」(「pkg」はパッケージの名前を表す)というラベルが付けられる。たとえば、symパッケージ内のパスごとデータ構造は、「sym_begin_path」というラベルの付いたルーチンによって割り付けられる。
チャンク・テーブルは、アクション1204によって作成されるパスごとデータ構造の例である。チャンク・テーブルは、1組のすべてのモデル化メモリを含み、記憶域管理とリーク検出のために使用される。本発明の一実施形態では、チャンク・テーブルは、チャンクを指し示すポインタの集合としてインプリメントされる。チャンクとは既知のメモリのモデル化された部分であり、これについては以下で詳しく説明する。概念的には、追跡されるあらゆるパスは関数の異なる実行であり、したがって、各実行をサポートするために新しいメモリ・モデルが作成される。本発明の一実施形態では、チャンク・テーブルはあるルーチンによって作成される。マイクロフィッシュの付録Aの実施形態では、「vim_begin_path」ルーチンがチャンク・テーブルを作成する。
アクション1204によって作成される他のパスごとデータ構造は記号テーブルである。記号テーブルは、名前(「記号」)を含む構文解析ツリー・ノードをメモリ・モデル内の位置と関連付ける。記号テーブルとは、記号テーブル・エントリ1300を指し示すポインタの集合である。各記号テーブル・エントリ1300は、現在の関数で使用される変数に対応する。
記号テーブル・エントリ1300を第13図に示す。記号テーブル・エントリ1300は、「parse tree pointer(構文解析ツリー・ポインタ)」1302、「symbol type(記号タイプ)」1304、「memory type(メモリ・タイプ)」1306、「symbol location(記号位置)」1308、「symbol location pointer(記号位置ポインタ)」1310、「parent index(親インデックス)」1312の各フィールドを含む。メモリ・モデル内の位置については以下で詳しく説明する。
フィールド「parse tree pointer」1302は、記号テーブル・エントリ1300によって表される記号を定義する現在の構文解析ツリー構造304内のノードを指し示す。フィールド「symbol type」1304は、記号テーブル・エントリ1300によって表される記号の種類を識別する。本発明の一実施形態では、フィールド「symbol type」1304の可能な値は「変数」、「定数」、「ルーチン」、「差」、「返却値」である。フィールド「memory type」1306は、記号テーブル・エントリ1300によって表される記号の値を保持するために使用されるメモリの種類を記述する。メモリ・タイプについては以下で詳しく説明する。
フィールド「symbol location」1308は、記号テーブル・エントリ1300によって表される記号の値を記憶するチャンクを指し示すコード化ポインタである。コード化ポインタについては以下で詳しく説明する。フィールド「symbol location pointer」1310は、「symbol location」1308によって指し示されるチャンクのコード化ポインタを記憶するチャンクのコード化ポインタ(すなわち、記述中の記号の値を指し示すポインタ)である。フィールド「parent index」1312は差のためだけに使用される。差とは、ポインタによって指し示される値を指す。記号テーブル・エントリが微分値を表すとき、フィールド「parent index」1312は、この微分値に到達するために使用されるポインタの記号テーブル内でのインデックスを保持する。たとえば、記号テーブル・エントリが*P(Pによって指し示される値)のエントリである場合、フィールド「parent index」1312は、ポインタPの記号テーブル内でのインデックスを含む。
アクション1204は、実行コンテキストブロック2100に情報をポストする。アクション1206はフィールド「current iteration」2108内のカウントを1(このパスの数を示す)だけ更新する。処理は返却値レイアウトアクション1206(以下では「アクション1206」と呼ぶ)へ移る。
アクション1206は、現在の関数の返却値用のモデル化メモリをレイアウトする。アクション1206はまた、返却値を記号テーブルに入れる。まず、アクション1206は、返却値を表すのに必要なメモリの量を求める。この量、すなわち返却値の長さはバイト単位で測定される。次いで、アクション1206は、返却値を表すのに必要なメモリの量を用いてメモリ作成ユニット1500を呼び出す。メモリ作成ユニット1500は、返却値を保持するモデル化メモリの部分を作成し、メモリ・モデル内の新たに作成された位置を指し示すコード化ポインタをアクション1206に返す。メモリ作成ユニット1500の動作については以下で詳しく説明する。次に、アクション1206は、作成された返却値位置を指し示すポインタをレイアウトする。第12図の実施形態では、ポインタの長さは4バイトである。前述のように、アクション1206はメモリ作成ユニット1500を呼び出し、モデル化メモリの適切なサイズの部分を作成し、新たに作成されたモデル・メモリ位置を指し示すコード化ポインタを受け取る。アクション1206は、返却値を指し示すポインタの位置に、返却値の位置のコード化アドレスを格納する。最後に、アクション1206は記号テーブルに返却値を入れる。
アクション1206は、記号テーブル・エントリ1300を作成する。返却値を含む構文解析ツリー・ノードを指し示すポインタは、フィールド「parse tree pointer」1302内に置かれる。「変数」の記号タイプはフィールド「symbol type」1302内に置かれる。「返却値」はフィールド「memory type」1306内に置かれる。返却値を保持するために作成された第1の位置を指し示すコード化ポインタは「symbol location」1308内に置かれる。返却値を指し示すポインタを格納するために作成された第2の位置を指し示すコード化ポインタはフィールド「symbol location pointer」1310内に置かれる。アクション1206では記号テーブルに記号差を格納することはないので、フィールド「parent index」1312は使用されない。本発明の一実施形態では、あるルーチンによって記号テーブルに記号テーブル・エントリ1300が入れられる。マイクロフィッシュの付録Aの実施形態では、「sym_add_symbol」というラベルの付いたルーチンが記号テーブルに記号テーブル・エントリ1300を入れる。処理は、パスに沿った文の処理アクション1208(以下では「アクション1208」と呼ぶ)へ移る。
アクション1208は、現在のパスをトラバースし各文の実行を模倣する責任を負う。アクション1208は、個々の各文タイプの実行をシミュレートまたはエミュレートするのに適切な処理を実行する。アクション1208の処理についての詳細な議論は、以下に見出し「文の分析」の下で提示する。現在のパスに沿って各文を処理するアクション1208が終了した後、処理は記号テーブル順序付けアクション1210(以下では「アクション1210」と呼ぶ)へ移る。本発明の一実施形態では、アクション1208はあるルーチンによって実現される。マイクロフィッシュの付録Aの実施形態では、「exe_execute_statement」というラベルの付いたルーチンがアクション1208の関数を実行する。
アクション1210は、記号テーブルをソートし、分析エンジン308によってトラバースされる各パスに関する記号テーブル上の順序を同じにする。オートモデル化では、いくつかの異なるパスの結果を比較する必要がある。記号テーブルをソートすると、現在のパスを実行した結果を他のパスを実行した結果と比較するのが容易になる。本発明の一実施形態では、記号テーブルはアルファベット順にソートされる。
記号テーブルをソートする理由は例を介して最もうまく説明することができる。オートモデル化中には、後述のように、オートモデル化のために必要な記号テーブル内のあらゆる記号が調べられる。記号テーブル・エントリ1300がポインタである場合は、ポインタ・チェーンをたどる。ポインタ・チェーンに沿った各位置は、チェーンの先頭にある記号の名前と、その前にある、この位置に到達するのに必要な各間接参照レベルについてのアスタリスク(「*」)とでラベル付けされる。たとえば、第14a図を参照するとわかるように、p1412は、「Locl」位置1416を指し示す記号テーブル1410内のポインタである。「Loc1」位置1416は、ポインタp1412から1間接参照レベルだけ離れており、「*p」とラベル付けされる。「Loc1」位置1416は「Loc2」位置1418を指し示す。「Loc2」位置1418は、ポインタp1412から2間接参照レベルだけ離れており、「**p」とラベル付けされる。
記号は、関数のパスに沿って記号に出会う順序で記号テーブル内に置かれる。関数のそれぞれの異なる経路をトラバースする際にそれぞれの異なる順序で記号に出会う。第14a図では、コード・パス上でポインタq1414よりも前にポインタp1412に出会っており、したがって、p1412は記号テーブル1410ではq1414よりも前にある。同じ関数中の異なる経路を表す第14b図では、ポインタp1412よりも前にポインタq1414に出会う。したがって、第14b図では、q1414は記号テーブル1420でp1412よりも前に記録される。
ポインタp1412およびq1414は、値ゼロを含むメモリ・モデル位置1424(Loc2)を指し示す共用メモリ・モデル位置1422(Loc1)を指し示す。前述のラベル付けステップを第14a図の記号テーブル1410に対して実行すると、結果は「*p=0」になる。この結果は、チェーンがポインタp1412から始まることに基づいて「Loc1」位置1416を*pとラベル付けすることから導かれる。ラベル付け演算を第14b図の記号テーブル1420に対して実行すると、結果は「*q=0」になる。この結果は、チェーンがポインタq1414から始まることに基づいて位置1422「Loc1」を*qとラベル付けすることから導かれる。2つのパスは共に同じ実際の結果を有するが、式が異なる(「*p=0」と「*q=0」)ので、結果を併合することは難しい。
記号テーブルをソートすると、ポインタp1412は常にポインタq1414よりも前に処理される。このように、2つのパスは共に結果を「*p=0」として表す。記号テーブルを順序付けることによって、2つのパスの結果を単一の結果に併合することができる。したがって、記号テーブルを順序付けると、オートモデル化処理によって、いくつかの異なるパスの結果を容易に比較することができる。本発明の一実施形態では、あるルーチンによって記号テーブルが順序付けされる。マイクロフィッシュの付録Aの実施形態では、ルーチン「sym_order_table」が記号テーブルを順序付ける。処理はアクション1210からリーク検出アクション1212(以下では「アクション1212」と呼ぶ)へ移る。
アクション1212はリーク検出処理を実行する。アクション1212は、すべてのモデル化メモリを巡回し、現在のパスを分析する間に累積されたメモリ割付けに関する情報を走査する。アクション1212は、現在の関数が終了する際にリークするメモリのチャンクを識別する。割付け時にはメモリの一部がリークするが、このことが、関数が終了した後に記号によって指摘されることはない。アクション1212は、リークした資源も検出する。アクション1212によって実行される処理の詳細な説明は、以下に見出し「リーク検出」の下で与える。処理はアクション1212からpragma_optionリセットアクション1214(以下では「アクション1214」と呼ぶ)へ移る。
アクション1214は、アクション1202で設定された構成オプションを再生する。現在の関数にプラグマが定義されている場合、アクション1214は、このプラグマに指定されている構成オプションをアクション1202で保存された値に設定する。アクション1214は、処理をパスごとデータ構造解放またはクリーンナップアクション1216(以下では「アクション1216」と呼ぶ)へ移す。
パスごと処理はアクション1216で終了し、パスごとに使用される記憶域がクリーンナップされ、グローバル・データ構造が現在のパスに関する情報で更新される。第13図の実施形態では、あるルーチンを実行することによって、パッケージ内のパスごとデータ構造が解放またはクリーンアップされる。このようなルーチンは、アクション1204で実行されるルーチンとは逆のパッケージ順で呼び出される。アクション1216によって呼び出されるルーチンは、exe、auto、cph、ins、sym、vim、err、mcil、ctxのパッケージ順で呼び出される。マイクロフィッシュの付録Aの実施形態では、アクション1216によって呼び出されるルーチンには「pkg_end_path」というラベルが付けられる。この場合、「pkg」はパッケージの名前を表す。たとえば、exeパッケージ内のパスごとデータ構造は、「exe_end_path」というラベルの付いたルーチンによって解放される。autoパッケージに対応するアクション1216によって実行されるルーチンは、現在のパスの「実行」に関する情報を収集し、現在の関数のモデル118を作成する際に助けとなるので特に重要である。オートモデル化については以下で詳しく説明する。アクション1216が完了すると、パスごと処理が終了する。
メモリ作成ユニット1500
前述のように、メモリ作成ユニット1500は、メモリをモデル化するために必要なデータ構造を作成する。分析エンジン308によって作成されたメモリ・モデルは、実行中にプログラムが使用するメモリを表している。分析エンジン308は構造上のメモリ・モデルを作成する。というのは、そのモデルは値ではなく値の内部合成物(composition)を単一ユニットとして模倣するからである。たとえば、C言語プログラムを分析する本発明の一実施形態では、倍長整数は、1つの単一アドレス可能値とは対照的に、個々にアドレス可能な4バイトの合成物として表されている。しかし、メモリ・モデルは、一時値を格納するために多くのコンピュータ・プログラムが使用するヒープ記憶域のように、物理的に隣接しているわけではない。
メモリ・モデルは、チャンク(chunk)・テーブルと、チャンク1700と、ポインタによってまとめてリンクされた格納値1800から構成される。前述のように、チャンク・テーブルはモデル化メモリのすべてを記録する。チャンク1700は、1つまたは複数の隣接メモリ位置をモデル化する。格納値1800は、1つまたは複数のメモリ位置(すなわち、チャンク1700)に格納された値を保持する。チャンク1700および格納値1800については以下に詳述する。メモリ作成ユニット1500の処理は、起点情報収集アクション1502(以下「アクション1502」という)から始まる。
アクション1502は、メモリが作成されるコンテキストを追跡するものである。アクション1502は、メモリ作成ユニット1500が処理を開始したときにコンテキスト情報をカプセル化する起点コンテキスト構造1600を作成する。起点コンテキスト構造1600は、後述するようにチャンク1700に格納される。起点コンテキスト構造については第16図に示す。起点コンテキスト構造1600は、「外部IDタイプ」1602と、「外部ID」1604と、「メモリ・タイプ」1606と、「ステートメントの作成元」1608と、「式の起点」1610と、「エミュレーション中フラグ」1612と、「ソース・コード・ファイル」1614と、「ソース行番号」1616と、「入力名」1618と、「出力名」1620というフィールドを含む。
フィールド「外部IDタイプ」1602は、その記憶域が作成された項目のタイプを示す。本発明の一実施形態で可能な項目タイプは、「記号」、「格納値」、「文字列」、「戻り値」、「未知」である。「格納値」については後述するが、「未知」は項目タイプを決定できないことを意味する。「記号」および「文字列」というタイプの項目は、当業者には周知のものである。フィールド「外部ID」1602は、モデル化したメモリの作成をトリガする項目を明確に識別する現行構文解析ツリー構造304内のノードを指すポインタを含む。
フィールド「メモリ・タイプ」1606は、何のためにそのメモリが作成されるのかを分類する。以下に詳述するように、フィールド「メモリ・タイプ」1606はモデル化のために使用する。その関数の外部で可視の項目のためにメモリを作成している場合、それは自動モデル化の際に使用されることになる。本発明の一実施形態では、モデル化したメモリのタイプは、定数、グローバル、グローバルのデリファレンス、スタティック、スタティックのデリファレンス、ローカル、パラメータ、パラメータのデリファレンス、ヒープ・メモリ、資源定義、資源、一時、未知、アドレス定数、文字定数、ゼロ定数である。当業者であれば、定数、グローバル、ローカル、スタティック、パラメータ、戻り値の各項目については分かるだろう。
前述のように、デリファレンスとは、ポインタが指し示す値を意味する。たとえば、グローバルのデリファレンスは、グローバル変数が指し示す値を保持するメモリ位置を示す。「未知」というメモリ・タイプは、モデル化したメモリの区画がその関数の外部で可視ではないことを示す。メモリ・タイプが「未知」の項目は、現行関数用のモデル118を作成する際に使用しない。一時値は、現行関数が実行する計算の中間ステップから得られ、現行構文解析ツリー構造304で識別される。ヒープ・メモリは現行関数が割り振ったメモリである。たとえば、C言語の「malloc(10)」という関数呼出しは10バイトのヒープ・メモリを作成する。資源および資源定義は、ファイルおよびウィンドウなど、関数が使用するオブジェクトを示す。
より一般的な「定数」メモリ・タイプは、分析エンジン308内の処理の最適化を見込んでおくために、アドレス、文字、文字列定数という特定のケースとは区別される。ゼロは頻繁に使用される数なので、分析エンジン308は、現行関数で使用するたびに定数ゼロのインスタンスを1つだけモデル化する。他の定数タイプとは対照的に、アドレス定数だけがデリファレンスされるので、リーク検出処理が改善される。項目が有効ポインタであるかどうかを判定するチェックは、文字定数については行う必要がないので、全体的な効率が改善される。最適化されたメモリ管理および意志決定によって、分析エンジン308のパフォーマンスが改善される。
フィールド「ステートメントの作成元」1608は、フィールド「外部ID」1604で識別された項目を含むステートメントを識別する現行構文解析ツリー構造304内の構文解析ツリー・ノードを指すポインタである。フィールド「式の起点」1610は、フィールド「外部ID」1604で識別された項目を含む式を識別する現行構文解析ツリー構造304内の構文解析ツリー・ノードを指すポインタである。フラグ「エミュレーション中フラグ」は、モデル化メモリがモデル118の実行のために作成されるときに真になる。フィールド「ソース・コード・ファイル」1614は、現行関数を含むソース・コード・ファイルの名前を識別する。フィールド「ソース行番号」1616は、フィールド「ステートメントの作成元」1608によって識別されるステートメントのフィールド「ソース・コード・ファイル」1614によって識別されるソース・コード・ファイル内の行番号を識別する。フィールド「入力名」1618は、作成中のモデル化メモリの区画に関連する元の格納値の名前を含む。フィールド「出力名」1620は、作成中のモデル化メモリの区画に関連する最終値の名前を含む。フィールド「入力名」1618およびフィールド「出力名」1620は、モデル化しているメモリ位置が現行関数の開始時(「入力名」1618)または終了時(「出力名」1620)のいずれでアクセス可能であるかを記録するために自動モデル化プログラムによって使用される。起点コンテキスト構造1600に適切に記入した後、処理はアクション1504に移行する。
アクション1504は、1つまたは複数の隣接メモリ位置用のモデルを作成するものである。メモリ位置は、アドレスによって明示的かつ明確に指定可能なメモリの最小単位である。通常、コンピュータ・メモリはバイト・アドレス可能であり、したがって、1つの位置は1バイトである。アクション1504は、チャンク1700を使用してメモリをモデル化する。チャンク1700については第17図に示す。チャンク1700は、「解放フラグ」1702と、「到達可能フラグ」1704と、「紛失フラグ」1706と、「メモリ・タイプ」1708と、「チャンク番号」1710と、「起点コンテキスト構造ポインタ」1712と、「格納値ポインタ」1714と、「元の格納値ポインタ」1716というフィールドを含む。
フラグ「解放フラグ」は、チャンク1700によってモデル化されたメモリ位置が解放されたときに真になる。フラグ「到達可能フラグ」1302は、そのメモリ位置が到達可能であるかどうかを判定するためにリーク検出処理が使用する。フラグ「紛失フラグ」1706は、モデル化したメモリが解放されるかまたはリークされるかどうかを判定できないときに真になる。紛失メモリの場合、関数が終了したあとでメモリを指し示すものが何もない可能性があるが、メモリを指すポインタのレコードがないというだけで、このようなポインタが存在しないことを意味するわけではない。たとえば、欠落モデルによってモデル化されるルーチンにメモリを割り振って、渡すことができる。分析エンジン308は、ルーチンに渡された割振りメモリに何が起きたのかを確かめることができない。したがって、そのメモリは「紛失」としてマークされる。フィールド「メモリ・タイプ」1708は、前述のフィールド「メモリ・タイプ」1606と同じ情報を保持する。フィールド「チャンク番号」1710は、チャンク1700用の固有の識別子である。フィールド「起点コンテキスト構造ポインタ」1712は、アクション1502で作成された起点コンテキスト構造1600を指し示す。フィールド「格納値ポインタ」1714は、モデル化メモリ位置にある現行値を指し示す。フィールド「元の格納値ポインタ」1716は、モデル化メモリ位置にある元の値を指し示す。
まず、アクション1504は、チャンク1700を再使用できるかどうかを判定するために、チャンク・テーブル内を反復してチャンク1700を調べる。アクション1504がチャンク1700を再使用できない場合、新しいチャンク1700を作成しなければならない。新しいチャンク1700を指すポインタはチャンク・テーブル内に配置される。チャンク番号1710には、新しいチャンク1700を明確に識別する番号が割り当てられる。フラグ「解放フラグ」1702、「到達可能フラグ」1704、「紛失フラグ」1706は、偽に初期設定される。フィールド「メモリ・タイプ」1708は、アクション1502で設定された「メモリ・タイプ」1606と等しくなるように設定される。フィールド「起点コンテキスト構造ポインタ」1712は、アクション1502で構築された起点コンテキスト構造1700を指し示すように設定される。次に処理は、格納値セットを作成するために値モデル化アクション1506(以下「アクション1506」という)に移行する。
アクション1506は、アクション1504で作成したチャンク1500によってモデル化された位置に配置された値をモデル化するものである。メモリ作成ユニット1500は、格納値セットを作成することによって値をモデル化する。格納値セットは格納値の集合である。各格納値は、1単位分のメモリを表すデータ構造である。第15図の実施形態では、メモリ作成ユニット1500は、Cコンピュータ言語のメモリ管理特性を模倣する。Cコンピュータ言語は、隣接バイト・セットとして値を割り振る。各格納値は1バイト分のメモリを表す。したがって、1セット分の格納値は、1つの値を格納するために使用するバイトの集合を表す。たとえば、正規整数は、通常、長さ4バイトである。アクション1506は、4つの格納値を作成し、それを格納値セット内に配置することによって整数をモデル化する。
アクション1506は、作成中のメモリの各バイトごとに1つの格納値を作成する。作成した各格納値を指すポインタは格納値セット内に配置される。したがって、格納値セットは、格納値を指すポインタの集合になる。格納値は、格納値ブロック1800によって表される。格納値ブロック1800については第18図に示す。格納値ブロック1800は、「起点ポインタ」1802と、「資源フラグ」1804と、「正確値既知フラグ」1806と、「初期設定済みフラグ」1808と、「想定値フラグ」1810と、「制約フラグ」1812と、「結果フラグ」1814と、「保護フラグ」1816と、「正確値」1818と、「入力からのバイト」1820と、「出力からのバイト」1822というフィールドを含む。
フィールド「起点ポインタ」1802は、アクション1502で作成した起点コンテキスト構造1600を指し示す。フラグ「資源フラグ」1804は、このデータ構造が格納値または格納資源のいずれを表すかを識別する。フラグ「資源フラグ」1804は、データ構造が格納値を表す場合に必ず偽になる。資源は格納値と同様に表されるが、格納値ブロック1800の代わりに格納資源ブロック1900を使用する。格納資源ブロック1900については後述する。フラグ「正確値既知フラグ」1806は、フィールド「正確値」1818が有効値を含むときに真になる。フラグ「想定値フラグ」1810は、この値が処理中に想定された場合に真になる。フラグ「制約フラグ」1812は、モデル118内の制約でこの値を使用できる場合に真になる。フラグ「結果フラグ」1814は、モデル118内の結果でこの値を使用できる場合に真になる。フラグ「保護」は、モデル118内の保護でこの値を使用できる場合に真になる。制約、結果、保護については「概念のモデル化」という見出しの項で詳述する。フィールド「正確値」1818は、モデル化メモリ位置に格納された正確値を含む。フィールド「入力からのバイト」1820は、この格納値に対応する(「元の格納値ポインタ」1716が指し示す)元の格納値セット内の特定のバイトを識別する。フィールド「出力からのバイト」1822は、この格納値に対応する(「格納値ポインタ」1714が指し示す)最終格納値セット内の特定のバイトを識別する。
あるいは、資源用のメモリをモデル化するためにメモリ作成ユニット1500を呼び出す場合、アクション1506は、格納資源ブロック1900を作成することになる。格納資源ブロック1900については第19図に示す。格納資源ブロック1900は、「起点ポインタ」1902と、「資源フラグ」1904と、「リーク可能フラグ」1906と、「到達可能フラグ」1908と、「紛失フラグ」1910と、「想定フラグ」1912と、「資源タイプ」1914と、「資源状態」1916というフィールドを含む。
フィールド「起点ポインタ」1902は、アクション1502で作成した起点コンテキスト構造1600を指し示す。フラグ「資源フラグ」1904は、このデータ構造が格納値または格納資源のいずれを表すかを識別する。フラグ「資源フラグ」1904は、データ構造が格納資源を表す場合に必ず真になる。フラグ「リーク可能フラグ」1906は、現行関数が終了したあとで資源を指し示すことができないときに真になる。フラグ「到達可能フラグ」1908は、後述するようにリーク検出処理の際に使用する。フラグ「紛失フラグ」1910は、現行関数が終了したあとで資源を指し示すかどうかを分析エンジン308が予測できないことを示す。フラグ「想定フラグ」1912は、分析エンジン308での処理中に資源が想定されたときに真になる。フィールド「資源タイプ」1914および「資源状態」1916は、モデル化メモリを必要とする資源のタイプと状態をそれぞれ保持する。必要な数の格納値ブロック1800または格納資源ブロック1900が作成され、格納値セット内に配置された後、処理はメモリ位置と値とのリンク・アクション1508(以下「アクション1508」という)に移行する。
アクション1508は、モデル化値(または資源)をモデル化メモリ位置にリンクするものである。これがチャンク1700について第1の格納値セットである場合、格納値ポインタ1714と元の格納値ポインタ1716の両方は、アクション1504で作成した格納値セットを指し示すように設定される。そうではない場合、格納値ポインタ1714だけが、アクション1514で作成した格納値セットを指し示すように設定される。このようにして、1つの位置に関する元の格納値セットと、1つの位置に関する最新格納値セットがチャンク1700に記憶される。格納値の中間インスタンスは自動モデル化には必要ないので廃棄される。モデル118は、関数が求める結果を記述するものであって、結果に到達する方法を記述するものではない。したがって、中間インスタンスではなく、格納値の初期インスタンスと最終インスタンスだけが、自動モデル化のために検査される。
メモリ作成ユニット1500用の処理は終了し、アクション1508はメモリ作成ユニット1500の呼出し側に新たにモデル化したメモリを指す符号化ポインタを返す。符号化ポインタは、チャンク1700を指すポインタと、格納値ポインタ1712が指し示す格納値セットへのオフセットからなる。モデル化メモリ内の位置はシミュレートしたメモリ位置なので、符号化ポインタが必要になる。たとえば、第20図に示すようにメモリをモデル化するために使用するデータ構造間のリンクの簡略図を参照されたい。チャンク2004は、チャンク・テーブル2002内の項目によって配置される。次にチャンク2004は、関連の格納値セット2006を指すポインタを含む。格納値セット2006へのオフセットは、格納値2008、2010、2012を指すポインタである。したがって、モデル化メモリ内では、真のメモリ位置とは異なり、単純な物理アドレスによって値にアクセスすることができない。このため、モデル・メモリ位置、またはより単純に位置は、格納値ブロック1800を指す符号化ポインタになる。
リーク検出
前述のように、リークは、パス内のステートメントが処理されたあとでパス分析の終わりにアクション1212で検出される。メモリ・リークは、マーク・スウィープ方法を使用して検出される。まず、アクション1212は、チャンク・テーブル内を反復し、各チャンクを到達不能としてマークする。チャンク1700は、フラグ「到達可能フラグ」1704を偽に設定することによって到達不能としてマークされる。次に、アクション1212は、記号テーブル内の各外部内を反復し、ポインタ連鎖のみを移動する。アクション1212は、ポインタ連鎖内で検出された各チャンク1700を到達可能としてマークする。チャンク1700は、フラグ「到達可能フラグ」1704を真に設定することによって到達可能としてマークされる。記号テーブルを処理した後、アクション1212は、チャンク・テーブル内を反復して各チャンク1700を検査する。各チャンクごとに、それがヒープ記憶域であって、解放も紛失もされておらず、依然として到達不能としてマークされている場合、そのチャンクはリーク済みとして報告される。本発明の一実施形態では、メモリ・リークは、対応する故障インジケータ106によって報告される。
また、アクション1212は資源リークも報告する。チャンク・テーブル内でもう一度反復が行われるが、今回のアクション1212は、資源を示すようにフィールド「メモリ・タイプ」1708が設定されたすべてのチャンク1700をサーチする。資源を定義する各チャンクごとに、対応する格納資源ブロック1900に対して問合せを行う。資源が到達可能ではなく、認識された状態の1つになっていない場合、それはリーク済みとして報告される。認識された状態としては、閉、解放、リリース済み、削除済みがある。本発明の一実施形態では、資源リークは対応する故障インジケータ106によって報告される。
ステートメント分析
アクション1208は、前述のように、現行パスに沿って各ステートメントの実行の模倣を担当する。分析中の現在のステートメントを現行ステートメントと称する。アクション1208は、さらに処理するために現行ステートメントを識別し、分散する。アクション1208については第22図のブロック図に示す。アクション1208用の処理は、プラグマ読取りアクション2202(以下「アクション2202」という)から始まる。
アクション2202は、現行ステートメント用にプラグマが定義されているかどうかを判定するものである。前に提示したように、プラグマは、プラグマの直後の関数またはステートメントに関する制御を設定するIntrinsa指示文である。ステートメントの直前のソース・コード内に配置されたIntrinsaプラグマは、その特定のステートメントのみを制御するための構成オプションを指定する。たとえば、以下のプラグマは、「a=1+2;」というステートメントのみに適用される。
#pragma INTRINSA “suppress=null_pointer, uninitialized”
a=1+2;
b=a;
「suppress」構成オプションに関する詳細は付録Bに記載されている。アクション2202は、プラグマを検出した場合、まず、プラグマによって指定された構成オプションの現行設定を保管し、次に、プラグマ内に指定された値に応じてこれらの構成オプションを設定する。処理は、アクション2202からコンテキスト情報更新アクション2204(以下「アクション2204」という)に移行する。
アクション2204は、実行コンテキスト・ブロック2100にコンテキスト情報を通知するものである。現行ステートメント2110は、現行ステートメントを表す現行構文解析ツリー構造304内のノードを指し示すように設定される。現行行番号2112は、現行ステートメントを含む現行関数を格納するファイル内の行番号に設定される。処理は、アクション2204から個々のステートメント・タイプに基づく直接処理アクション2206(以下「アクション2206」という)に移行する。
アクション2206は、さらに処理するためにステートメント・ユニットに分散することにより、個々のステートメントを処理するものである。アクション2206は、まず、分析中のステートメントのタイプを識別する。次にアクション2208は、処理制御を対応するステートメント・ユニットに移転する。第22図の実施形態に関して、表3は、ステートメントのタイプと呼び出されたステートメント・ユニットとの対応関係を示している。「ステートメント・ユニット」という列に列挙したモジュールについては以下に詳述する。「ステートメント・タイプ」という列に列挙したステートメント・タイプは、当業者にとって周知ものである。制御がアクション2206に戻ると、処理は、プラグマ・オプション・リセット・アクション2208(以下「アクション2208」という)に移行する。
アクション2208は、アクション2202で設定した構成オプションを復元するものである。現行ステートメント用にプラグマが定義されている場合、アクション2208は、プラグマ内に指定された構成オプションをアクション2202で保管した値に設定する。アクション2208は処理制御を開始アクション制御に返す。
次にステートメント・ユニットの説明に移行すると、ブロック・ユニットは、ブロック・ステートメント内のステートメントによるループを実行する。ブロック・ステートメントは、しばしば複文と呼ばれるが、1つの構文ユニットを形成する1組のステートメントである。通常、ブロック・ステートメントは、Cプログラミング言語で書かれた関数内の最高レベルのステートメントである。ブロック・ユニットについては、論理流れ図2300(第23図)として詳細に示す。
パス終了判断2301(以下「判断2301」という)では、現在のブロックが終了したかどうかを確認するためにチェックを行う。nullまたはexitステートメントが前に処理されている場合、現行ブロック・ステートメントの分析は完了し、論理流れ図2300による処理、したがって、ブロック・ユニットは終了する。現在のブロックが依然として活動状態である場合、処理は、gotoステートメントが処理されているかどうかを判定するgotoケース判断2302(以下「判断2302」という)に移行する。第23図の実施形態では、goto処理は、gotoパラメータに問い合わせることによって識別される。マイクロフィッシュの付録Aの実施形態では、gotoパラメータは「goto_statement」と命名されている。gotoステートメントがシミュレートされることをgotoパラメータが示している場合、処理はターゲット判断2303(以下「判断2303」という)に移行し、そうではない場合、処理制御はステートメント分析アクション2305(以下「アクション2305」という)に移行する。
判断2303は、活動gotoステートメントのターゲットであるステートメントに到達したかどうかを確認するためにテストを行う。判断2303は、ブロック内の現行ステートメントを表す現行構文解析ツリー・ノードを指すポインタと、gotoターゲット・ステートメントを表す現行構文解析ツリー・ノードを指すポインタとを比較する。2つのポインタが一致する場合、ブロック内の現行ステートメントはgotoターゲット・ステートメントである。gotoターゲット・ステートメントに到達している場合、処理はgoto切断アクション2304(以下「アクション2304」という)に移行する。ブロック内の現行ステートメントがgotoターゲット・ステートメントではない場合、処理は最終判断2306(以下「判断2306」という)に移行する。
アクション2304は、処理中の活動gotoステートメントがないことを示すためにgotoパラメータを偽に設定する。アクション2304が完了した後、処理はアクション2305に移行する。アクション2305はブロック内の現行ステートメントを分析するものである。アクション2305は、ブロック内の現行ステートメントを表す現行構文解析ツリー構造304内のノードを指すポインタを取り出し、処理制御とともにそのポインタを再帰的にアクション1208に転送する。制御がアクション2305に戻ると、処理は最終判断2306に移行する。
判断2306は、現在のブロック・ステートメント内の最終ステートメントが処理されたかどうかを判定する。判断2306が真になる場合、論理流れ図2300による処理、したがって、ブロック・ユニットは終了する。そうではない場合、最終ステートメントに到達していないので、処理は次の獲得アクション2309(以下「アクション2309」という)に移行する。アクション2309は、ブロック内の次のステートメントを獲得し、判断2301に制御を移転して、現在のブロック・ステートメントの処理を続行する。
式ユニットは式を処理するものである。入力として、式ユニットは、処理すべき式を表す現行構文解析ツリー構造304内のノードを指すポインタを受け取る。出力として、式ユニットは、式の結果を保持する位置を指すポインタを返す。「式」という用語は、本明細書では、KernighanおよびRitchieによるThe C programming language、185(Prentice−Hall、1978年)に定義されているように使用する。ステートメントは、セミコロンとともにそのあとに続くことによって、式から構築することができる。本発明の一実施形態では、式ユニットはルーチンによって実現される。マイクロフィッシュの付録Aの実施形態では、式ユニットは「exe_evaluate_expr」ルーチンによって実現される。式ユニットについては、論理流れ図2400(第24図)として詳細に示す。
式の処理は、null式判断2402(以下「判断2402」という)から始まる。判断2402は、入力式がnull式と等しいかどうかを判定する。入力式がnull式と等しいときは、いかなるアクションも不要であり、論理流れ図2400による処理、したがって、式ユニットは終了する。そうではない場合、入力式がnull式と等しくないときは、処理は現行コンテキスト保管アクション2404(以下「アクション2404」という)に移行する。アクション2404は、現行式2114の値を保管する。処理は、入力式を表す現行構文解析ツリー構造304内のノードを指すポインタを現行式2114に格納する新コンテキスト設定アクション2406(以下「アクション2406」という)に移行する。古いコンテキスト情報が保管され、新しいコンテキストが設定された後、処理は値判断2408(以下「判断2408」という)に移行する。
判断2408は、入力式が値であるかどうかを判定する。構文解析ツリーに関する前述の説明に戻ると、値は構文解析ツリー内のリーフノードである。一実施形態の値は、定数、変数、可変アドレス、またはルーチン・アドレスにすることができる。入力式が値である場合、処理は値探索アクション2410(以下「アクション2410」という)に移行し、そうではない場合、処理は演算判断2422(以下「判断2422」という)に移行する。
アクション2410は、入力式の値を決定するものである。構文解析ツリー構造304は各値ごとに固有の宣言ノードを有する。宣言ノードは、そのタイプやその内容など、値に関する情報を有する。アクション2410は、対応する宣言ノードを指すポインタを入力式を表すノードから取り出す。また、宣言ノードを指すポインタは、本明細書ではexternal_idともいう。これは、記号テーブル内の記号を探索するために使用するexternal_idである。値の内容の判定は、参照した宣言ノードによって行われる。参照した宣言ノードが値の内容を含まない場合、その値は「未知」としてフラグが付けられる。処理は、アクション2410から記号テーブル内検出判断2412(以下「判断2412」という)に移行する。
判断2412は、値が記号テーブルに格納されているかどうかを判定するものである。判断2412は、アクション2410で検出したexternal_idと、記号テーブル項目内の構文解析ツリー・ポインタ1302とを比較する。一致が検出された場合、その値は記号テーブル内にあり、処理はコンテキスト復元アクション2428(以下「アクション2428」という)に移行する。その値が記号テーブル内で検出されない場合、処理はメモリ作成アクション2414(以下「アクション2414」という)に移行する。
アクション2414は、現行式用に(すなわち、値用に)モデル化メモリをレイアウトするものである。アクション2414は、現行関数の戻り値用にモデル化メモリをレイアウトする前述のアクション1206と同様のものである。まず、アクション2414は、現行式を表すために必要なメモリの量を決定する。次に、アクション2414は、メモリ作成ユニット1500を呼び出して、現行式を表すために必要な量のメモリをモデル化する。次にアクション2414は、(参照した宣言ノードで検出された)現行式の内容を新たにモデル化したメモリに格納する。現行式が変数である場合、アクション2414は作成したばかりの現行式位置を指すポインタをレイアウトする。アクション2414は、メモリ作成ユニット1500を呼び出して、モデル化メモリのポインタ・サイズの区画を作成する。アクション2414は、現行式の位置の符号化アドレスを現行式を指すポインタ用の位置に格納する。処理はアクション2414から非ゼロ定数判断2416(以下「判断2416」という)に移行する。
判断2416は、現行式が非ゼロ定数であるかどうかを判定するものである。現行式が非ゼロ定数である場合、処理はアクション2428に移行し、そうではない場合、処理は記号テーブルへの追加アクション2418(以下「アクション2418」という)に移行する。アクション2418は、現行式を表すための記号テーブル項目1300を作成し、新たに作成した記号テーブル項目1300を記号テーブルに格納する。ゼロは記号テーブル内に配置される唯一の定数である。ゼロは、定数ゼロを使用するたびに何度もメモリをモデル化するのを回避するために最適化として記号テーブル内に配置される。処理はアクション2418からスタティックおよびグローバル変数のリスト保守アクション2420(以下「アクション2420」という)に移行する。
アクション2420は、自動モデル化のために、グローバル変数のリストとスタティック変数のリストを保守するものである。変数タイプ情報は現行式に対応する宣言ノードに記録されている。本発明の一実施形態では、変数は、グローバル、スタティック、またはローカルのいずれかのタイプにすることができる。現行式がグローバル変数である場合、アクション2420はグローバル変数リストを更新し、現行式がスタティック変数である場合、アクション2420はスタティック変数リストを更新することになる。処理はアクション2420からアクション2428に移行する。
入力式が値ではない場合、演算判断2422(以下「判断2422」という)は、現行式が演算であるかどうかを判定することになる。現行式が演算である場合、処理は演算処理アクション2424(以下「アクション2424」という)に移行する。アクション2424については以下に詳述する。現行式が演算ではない場合、処理は非評価ケース・アクション2426(以下「アクション2426」という)に移行する。アクション2426は、現行式を識別できない場合に適切なエラー・コードを発行する。現行式が分析エンジン308によってサポートされていない場合、いかなるアクションも行われない。たとえば、第24図の実施形態では、「new」と「delete」というC++式はサポートされていない。処理はアクション2426からアクション2428に移行する。
アクション2428は、アクション2404で保管した値を現行式2114に復元する。次に、論理流れ図2400による処理、したがって、式ユニットは終了する。終了すると、式ユニットは開始サイト制御に制御を移転する。
演算を処理するアクション2424については、論理流れ図2500(第25a図、第25b図)に示す。アクション2424は、どのタイプの演算を現行式が表しているかを判定し、適切な処理を実行する。演算式は、演算子と1つまたは複数のオペランドから構成される。オペランドも式である。処理は、現行式が関数呼出しを表すかどうかを判定する関数呼出し判断2502(以下「判断2502」という)から始まる。現行式が関数呼出しである場合、処理は、呼び出した関数をエミュレートする関数エミュレート・アクション2504(以下「アクション2504」という)に移行し、そうではない場合、処理は短絡演算判断2506(以下「判断2506」という)に移行する。
アクション2504は、その対応モデル118を実行することによって関数をエミュレートする。モデル118を実行すると、アクション2504は、対応する関数がメモリ・モデルに対してどのような影響を及ぼすか(関数の外部効果)を判定することができる。実行すべき関数が欠落モデルによって表される場合、アクション2504は、関数呼出しが正常に完了すると想定するだけである。付録Fには、アクション2504を実現するために使用する一実施形態の擬似コードが提示されている。アクション2504が完了すると、論理流れ図2500による処理、したがって、アクション2424は終了する。
判断2506は、現行式が短絡演算であるかどうかをチェックする。短絡演算子である論理積(&&)および論理和(||)はこのように呼ばれる。というのは、(おそらくすべてのオペランドが評価される前に)演算の真理値が決定されると、ただちに演算の評価が停止するからである。現行式が短絡演算である場合、処理はLHS式評価アクション2508(以下「アクション2508」という)に移行する。アクション2508は、プロセス制御を式ユニット(アクション2402)に移転することにより、演算の左辺式(すなわち、左辺オペランド)を評価する。左辺式を評価した後、処理は、入力式の真理値が決定されたかどうかを判断する真理値決定判断2510(以下「判断2510」という)に移行する。入力式が論理積であって左辺式が偽と評価されるか、または入力式が論理和であって左辺式が真と評価された場合、入力式の真理値が決定され、論理流れ図2500による処理、したがって、アクション2424は終了する。そうではない場合、処理は、処理を式ユニット(アクション2402)に移行することにより現行式の右辺(すなわち、右辺オペランド)を評価するRHS式評価アクション2512(以下「アクション2512」という)に移行する。右辺式が評価された後、論理流れ図2500による処理、したがって、アクション2424は終了する。本発明の一実施形態では、アクション2424の処理はルーチンによって実行される。マイクロフィッシュの付録Aの実施形態では、「exe_evaluate_operation」ルーチンがアクション2424の処理を実行する。
現行式が短絡演算ではない場合、処理は、現行式が3項演算子「?:」であるかどうかを判定する疑問符演算判断2514(以下「判断2514」という)に移行する。現行式が疑問符演算である場合、処理は、疑問符演算のテスト式を評価するテスト式評価アクション2516(以下「アクション2516」という)に移行する。テスト式は、式ユニットを呼び出すことによって評価される。テスト式が評価された後、処理は、テスト式の真理値を検査するテスト式判断2518(以下「判断2518」という)に移行する。テスト式が真と評価された場合、処理は、「真」というテスト式結果に対応する式を評価する「真」式評価アクション2520(以下「アクション2520」という)に移行する。そうではない場合、処理は、真ではないテスト式結果に対応する式を評価する「偽」式評価アクション2522(以下「アクション2522」という)に移行する。アクション2520またはアクション2522の後、論理流れ図2500による処理、したがって、アクション2424は終了する。
現行式が疑問符演算ではない場合、処理は、現行式がカンマ演算であるかどうかを判定するカンマ演算判断2524(以下「判断2524」という)に移行する。現行式がカンマ演算である場合、処理はLHS評価(戻り値なし)アクション2526(以下「アクション2526」という)に移行する。アクション2526は、カンマ演算の左辺式を評価する。アクション2526は、左辺式に関して返された値を必要としないので、空ポインタを式ユニットに渡す。左辺式の評価後、処理は、カンマ演算の右辺式を評価するRHS評価(戻り値)アクション2528(以下「アクション2528」という)に移行する。アクション2528は戻り値を必要とするので、式の結果用の位置を指すポインタによって式ユニットを呼び出す。アクション2528の後、論理流れ図2500による処理、したがって、アクション2424は終了する。
現行式がカンマ演算ではない場合、処理は、現行式がビット・フィールドまたはフィールド演算であるかどうかを判定するビット・フィールドおよびフィールド演算判断2530(以下「判断2530」という)に移行する。現行式がビット・フィールドまたはフィールド演算である場合、演算子が構造内のフィールドを参照することを意味し、処理はlhs式評価アクション2540(以下「アクション2540」という)に移行する。
アクション2540は、式評価ユニットを呼び出すことにより、左辺オペランド(すなわち、lhs式)を評価する。左辺式は、ビット・フィールドまたはフィールド演算が参照する構造を指すポインタである。左辺式が評価された後、処理制御は、値必要判断2452(以下「判断2542」という)に移転する。
判断2542は、ビット・フィールドまたはフィールド演算がその構造から値を取り出すかどうかを判定する。演算が値を必要とする場合、処理はメモリ作成アクション2544(以下「アクション2544」という)に移行し、そうではない場合、処理制御はrhs argとしてのオフセットの使用アクション2546(以下「アクション2546」という)に移転する。アクション2544は、演算が参照する値用のメモリを作成するものである。アクション2544は、メモリ作成ユニット1500を呼び出して、構造参照の結果得られる値を保持するために十分な大きさのモデル化メモリの区画を作成する。必要なモデル化メモリが作成された後、処理はアクション2546に移行する。
アクション2546は、右辺オペランドに対応する引数情報ブロック2600に、位置情報ではなくフィールド・オフセット情報を記入することにより、演算ユニットを呼び出すための準備を行う。引数情報ブロック2600については以下に詳述する。処理制御は演算評価アクション2538に移転する。
現行式がビット・フィールドまたはフィールド演算ではない場合、処理はLHS式評価アクション2532(以下「アクション2532」という)に移行する。処理制御がアクション2532に到達した場合、現行式が特殊ケースの処理を必要としないことが分かっており、「通常」演算処理が始まる。アクション2532は、現行式の左辺を評価するものである。すべての演算は少なくとも1つの左辺オペランドを有することになる。左辺式が評価された後、処理は、現行式が2項演算であるかどうかを判定する2項演算判断2534(以下「判断2534」という)に移行する。現行式が2項演算である場合、処理は、現行式の右辺を評価するRHS式評価アクション2536(以下「アクション2536」という)に移行する。右辺式が評価された後または現行式が単項演算であると判定された後、処理は演算評価アクション2538(以下「アクション2538」という)に移行する。
アクション2538は、評価すべき演算を表す演算子と、引数情報ブロック2600(第26図)内にパッケージ化された演算子の各オペランドとを指定して演算ユニットを呼び出すことにより、演算を評価するものである。前述のように、現行式がビット・フィールドまたはフィールド演算である場合、右辺オペランドに対応する引数情報ブロック2600は実際には、モデル化メモリ位置とは対照的に、構造内へのオフセットを表す。引数情報ブロック2600は、「位置ポインタ」2602と、「サイズ」2604と、「ブール」2606と、「ポイントからサイズ」2608と、「ポイント間からサイズ」2610と、「ビット・フィールド・フラグ」2612と、「ビット・オフセット」2614と、「ビット・サイズ」2616と、「印字式」2618というフィールドを含む。
フィールド「位置ポインタ」2602は、現在の引数ブロック2600に対応する引数のモデル化メモリ用の符号化ポインタに設定される。各オペランドは、別々の引数ブロック2600によって記述される。フィールド「サイズ」2604は、フィールド「位置ポインタ」2602が指し示すメモリのサイズに設定される。一部の演算はブール値を返し、返されたブール値はフィールド「ブール」2606に格納される。フィールド「ポイントからサイズ」2608は、フィールド「位置ポインタ」2602が指し示すモデル化メモリ位置にある値が指し示すもののサイズを保持する。フィールド「ポイント間からサイズ」2610は、フィールド「位置ポインタ」2602が参照する値が指し示す位置にある値が指し示すもののサイズを保持する。フラグ「ビット・フィールド・フラグ」2612は、フィールド「位置ポインタ」2602がビット・フィールドであるときにオンになる。フィールド「ビット・オフセット」2614は、ビット・フィールドの開始点を示す。フィールド「ビット・サイズ」2616は、ビット・フィールドのビット単位のサイズを保持する。フィールド「印字式」2618は、引数情報ブロック2600に記述された値を含む式を印字可能なフォーマットで格納する。
演算ユニットから戻った後、論理流れ図2500による処理、したがって、アクション2424は終了する。終了すると、アクション2424はアクション2428(第24図)に処理を移転する。
演算ユニットについては論理流れ図2700(第27図)に示す。一般に、演算ユニットは組込みモデルを実行して、演算の結果を判定する。組込みモデルはモデル118と同様のものである。モデル制約と同様に、実行すべき演算について真になるべきものが真になっていることを確認するテストが行われる。次に、モデル結果と同様に、演算を実行したあとで真であることが確認されるものを記述する結果が生成される。演算ユニットはいつでも結果の位置を返す。返された位置が空になることもありうる。演算ユニットの処理はテスト選択アクション2702(以下「アクション2702」という)から始まる。本発明の一実施形態では、演算ユニットの処理はルーチンによって行われる。マイクロフィッシュの付録Aの実施形態では、「ins_evaluate_operation」というルーチンが演算ユニットの処理を実行する。
アクション2702は、評価中の演算について実行すべきテストを選択する。実行するために使用可能なテストとしては、「comparable」、「valid_pointer」、「initialized」、「non_zero」がある。「comparable」テストは、2つのポインタが同じ格納値セットを指し示すかどうかを判定する。分析エンジン308はメモリを正確に複製するわけではないので、2つのポインタは、モデル化メモリの同じ区画を指し示す場合のみ、比較することができる。「valid_pointer」テストは、その位置が有効なポインタ、すなわち、モデル化メモリのうちの現在使用中の区画を指すポインタを含むかどうかを判定する。「initialized」テストは、所与の位置に値があるかどうかを判定する。「initialized」テストは、その位置に対応する格納値ブロック1800を調べ、フラグ「初期設定済みフラグ」1808をチェックして、その値が初期設定されているかどうかを判定する。「non_zero」テストは、ある位置が定数ゼロ以外の値を含むかどうかを判定する。このテストは、ゼロに等しい除数に関するスクリーニングのために使用する。各演算ごとに、適用するテストと、そのテストが適用されるオペランドを付録Cに列挙する。
適切なテストが選択された後、処理はフィールド演算子判断2704(以下「判断2704」という)に移行する。判断2704は、分析中の演算子がビット・フィールドまたはフィールド演算子であるかどうかを判定する。分析中の演算子がフィールド演算子である場合、処理はオフセット・メモリ作成アクション2706(以下「アクション2706」という)に移行し、そうではない場合、処理は単項演算子判断2718(以下「判断2718」という)に移行する。
アクション2706は、右辺引数に対応する引数情報ブロック2600に格納されたフィールド構造内のオフセットを保持するためにモデル化メモリの区画を作成する。このオフセットは、新たに作成したモデル化メモリ位置に格納される。処理はテスト実行アクション2708(以下「アクション2708」という)に移行する。
アクション2708は、アクション2702で選択したテストを実行する。実行すべき各テストごとに、アクション2708は、分析中の演算子と、テスト中のオペランドに対応する引数情報ブロック2600と、テストが成功したかどうかを報告する条件変数とを指定してvim基本テスト・ユニットを呼び出す。vim基本テスト・ユニットは、指示したテストを実行するためにメモリ・モデルに問い合わせる。vim基本テスト・ユニットについては以下に詳述する。選択したすべてのテストが実行された後、処理は加算演算子適用アクション2710(以下「アクション2710」という)に移行する。
アクション2710は、分析中の演算子と、左辺オペランド(すなわち、構造の位置)に対応する引数情報ブロック2600と、右辺オペランド(すなわち、構造内へのオフセットの位置)に対応する引数情報ブロック2600と、結果位置を指すポインタと、演算によって1が生成される場合に真理値を保持するための条件変数とを指定してvim基本評価ユニットを呼び出すことにより、ポインタ加算演算子を評価する。vim基本評価ユニットは、指示した演算の結果を達成するようにメモリ・モデルを操作する。vim基本評価ユニットについては以下に詳述する。ポインタ加算演算子の結果は、構造内の参照フィールドを指すポインタである。加算演算を評価した後、処理はフィールド値必要判断2712(以下「判断2712」という)に移行する。
判断2712は、フィールド演算子がフィールドの値を必要とするかどうかを判定する。フィールド演算子は、構造内の参照フィールドの内容を返すときに値を必要とする。フィールド値が必要である場合、処理はテスト実行アクション2714(以下「アクション2714」という)に移行し、そうではない場合、論理流れ図2700による処理、したがって、演算ユニットは終了する。
アクション2714は、アクション2708と同様に、アクション2702で選択したテストを実行する。テストが実行された後、処理はデリファレンス演算子適用アクション2716(以下「アクション2716」という)に移行する。アクション2716は、分析中の演算子と、左辺オペランド(すなわち、構造内の参照フィールドを指すポインタ)に対応する引数情報ブロック2600と、結果位置を指すポインタと、演算によって1が生成される場合に真理値を保持するための条件変数とを指定してvim基本評価ユニットを呼び出すことにより、ポインタ・デリファレンス演算子を評価する。vim基本評価ユニットは、指示した演算の結果を達成するようにメモリ・モデルを操作する。ポインタ・デリファレンス演算は、構造内の参照フィールドの内容を返す。ポインタ・デリファレンス演算子を評価した後、論理流れ図2700による処理、したがって、演算ユニットは終了する。
判断2718は、分析中の演算子が単項演算子であるかどうかを判定する。分析中の演算子が単項演算子である場合、処理はテスト実行アクション2720(以下「アクション2720」という)に移行し、そうではない場合、処理は2項演算子判断2724(以下「判断2724」という)に至る。アクション2720は、アクション2708と同様に、アクション2702で選択したテストを実行する。選択したすべてのテストが実行された後、処理は単項演算子適用アクション2722(以下「アクション2722」という)に移行する。アクション2722は、分析中の演算子と、左辺オペランドに対応する引数情報ブロック2600と、結果位置を指すポインタと、演算によって1が生成される場合に真理値を保持するための条件変数とを指定してvim基本評価ユニットを呼び出すことにより、単項演算子を評価する。単項演算を評価した後、処理は未決定関係判断2730(以下「判断2730」という)に移行する。
演算子が単項演算子ではない場合、処理は、演算子が2項演算子であるかどうかを判定する判断2724に移行する。演算子が2項演算子である場合、処理はテスト実行アクション2726(以下「アクション2726」という)に移行し、そうではない場合、処理は判断2730に至る。アクション2726は、アクション2720と同様に、アクション2702で選択したテストを実行する。テストが実行された後、処理は2項演算子適用アクション2728(以下「アクション2728」という)に移行する。
アクション2728は、分析中の演算子と、左辺オペランドに対応する引数情報ブロック2600と、右辺オペランドに対応する引数情報ブロック2600と、結果位置を指すポインタと、演算によって1が生成される場合に真理値を保持するための条件変数とを指定してvim基本評価ユニットを呼び出すことにより、2項演算を評価する。2項演算を評価した後、処理は判断2730に移行する。
判断2730は、評価した演算が、「不明」値であると評価された関係演算であったかどうかを確認するためのチェックを行う。モデル化メモリが実メモリの正確な複製ではない場合の結果の1つは、モデル化メモリが3値真理論理を使用することである。モデル化メモリ内の真理値は、「真」、「偽」、「不明」のいずれかになる。「不明」条件は、真のメモリに関する知識が不完全であることによる。演算の結果、「不明」条件が発生した場合、モデル化メモリの3値真理論理を2値真理論理に変換しなければならない。判断2730が真になる場合、処理は条件選択アクション2732(以下「アクション2732」という)に移行する。アクション2732は、CPH条件選択ユニットを呼び出すことによって条件を選択する。CPH条件選択ユニットについては以下に詳述する。選択が行われると、アクション2732は、位置に対応する格納値ブロック1800でフラグ「想定値フラグ」1810をオン(真)に設定する。処理は情報想定アクション2734(以下「アクション2734」という)に移行する。
アクション2732で選択が行われた場合、その選択の含意を示すためにモデル化メモリを必ず更新しなければならない。式の結果を選択することは、その式で使用するオペランドに関する派生効果を有する。たとえば、以下のコード・サンプルを検討する。
変数iに関する情報が一切不明である場合、ゼロと同等であるiを評価すると、「不明」値が返されることになる。変数iと定数ゼロとを比較するための情報がまったくないので、vim基本評価ユニットによって「不明」という値が返される。iがゼロと同等であると想定するという選択が行われた場合、コード・パスに沿って今後のステートメントで変数iを一貫して使用するためには、iがゼロと等しいことを反映するようにメモリを更新しなければならない。アクション2734は、モデル化メモリを適切に更新するためにvim想定ユニットを呼び出す。vim想定ユニットについては以下に詳述する。vim想定ユニットから戻ると、論理流れ図2700による処理、したがって、演算ユニットは終了する。終了すると、処理制御は開始サイト制御に返される。
選択点を解決するための条件の選択は、CPH条件選択ユニットによって行われる。CPH条件選択ユニットについては論理流れ図3300(第33図)に示す。処理は、選択実行判断3302(以下「判断3302」という)から始まる。判断3302は、実行すべき選択がアクション1108で構築したパスの一部に対応するかどうかを判定する。実行すべき選択がアクション1108で決定したパス上の選択点によってすでに表されている場合、処理は選択アクション3304(以下「アクション3304」という)に移行する。アクション3304はアクション1108で構築したパスが指示する選択を行い、論理流れ図3300による処理、したがって、CPH条件選択ユニットは終了する。
判断3302が偽を返す場合、いかなる選択も前もって決定されていないので、処理はランダム選択アクション3306(以下「アクション3306」という)に移行する。解決するためにCPH条件選択ユニットが呼び出された未解決の選択点が選択点ノードに対応することに留意されたい。また、未解決の選択点に関して可能な解決は、その選択点ノードから出る選択エッジに対応する。アクション3306は、未調査の選択エッジ間でランダム選択を行うことによって、結果(選択)を抜き取る。選択が行われた後、処理はCPHツリー更新アクション3308(以下「アクション3308」という)に移行する。
アクション3308は、選択点ノードで選択したエッジ選択にマークを付けるものである。この選択点ノードがすでにCPHツリー上にあるものではない場合、アクション3308はこれをツリーに挿入する。CPHツリーが更新された後、論理流れ図3300による処理、したがって、CPH条件選択ユニットは終了する。終了すると、処理制御は開始サイト制御に戻る。本発明の一実施形態では、CPH条件選択ユニットはルーチンによって行われる。マイクロフィッシュの付録Aの実施形態では、「cph_choose_condition」というルーチンがCPH条件選択ユニットの処理を実行する。
if−elseユニットは、if−elseステートメントを処理するものである。if−elseユニットについては論理流れ図2800(第28図)として詳細に示す。if−elseユニットの処理は、テスト式評価アクション2802(以下「アクション2802」という)から始まる。アクション2802はif−elseステートメントのテスト式を評価する。前述のように、式ユニット(アクション2402)を呼び出すことにより、式を評価する。テスト式が評価された後、処理は、テスト式の結果を検査するテスト式結果判断2804(以下「判断2804」という)に移行する。テスト式が真であると評価された場合、処理は、if式を評価する「if」式評価アクション2806(以下「アクション2806」という)に移行する。そうではない場合、処理は、偽式を評価する「偽」式評価アクション2808(以下「アクション2808」という)に移行する。アクション2806または2808後に、論理流れ図2800の処理、したがって、if−elseユニットは終了する。終了すると、if−elseユニットは開始サイト制御に制御を移転する。
whileループ、do whileループ、forの各ユニットは、いずれもループ実行ユニットを呼び出して、それぞれに対応するステートメントの処理を実行する。3つのユニット間の唯一の違いは、forユニットはループ実行ユニットを呼び出す前に初期設定ステートメントを評価することである。forユニットは、処理制御をアクション1208に移転することにより、初期設定ステートメントを評価する。ループ実行ユニットについては論理流れ図2900(第29図)として詳細に示す。本発明の一実施形態では、ループ実行ユニットはルーチンによって行われる。マイクロフィッシュの付録Aの実施形態では、「exe_loop」というルーチンがループ実行ユニットの処理を実行する。
ループ実行ユニットは、ループ・ステートメントを指し示すために実行コンテキスト・ブロック2100のフィールド「現行ステートメント」2110を更新するステートメント・コンテキスト設定アクション2902から処理を始める。処理は、現行ステートメントがforまたはwhileループであるかどうかを判定するforまたはwhileループ判断2904に移行する。現行ステートメントがforまたはwhileループである場合、処理は、条件偽またはループ終了判断2906(以下「判断2906」という)に移行する。そうではない場合、処理はループ未終了判断2910(以下「判断2910」という)に至る。
判断2906は、式評価ユニットを呼び出すことにより、テスト条件式を評価する。判断2906は、条件が偽であるかまたはループが終了したかどうかを判定する。基本的にこれは、ループの本体より前にテストが評価されることを意味する。ループ条件が偽であるかまたはループが終了した場合、処理は、ループ終了フラグをオンにして、ループが完了したことを記憶するループ完了記憶アクション2908に移行する。そうではない場合、処理は判断2910に移行する。
判断2910は、ループ終了フラグに問い合わせて、ループが完了したかどうかを判定する。ループが完了していない場合、処理はアクション2912に移行する。そうではない場合、処理はdo whileループ判断2918(以下「判断2918」という)に移行する。アクション2912は、ループ本体内のすべてのステートメントを実行する。各ステートメントは、アクション1208を呼び出すことによって実行される。ループ本体内の各ステートメントが実行されると、処理は、現行ステートメントがforループであるかどうかを判定するforループ判断2914に移行する。現行ステートメントがforループである場合、処理は、式ユニットを呼び出すことにより増分式を評価するアクション2916に移行する。増分式が評価された後、または現行ステートメントがforループではない場合、処理は判断2918に移行する。
判断2918は、現行ループがdo whileループであるかどうかを判定する。現行ループがdo whileループである場合、処理は、式ユニットを呼び出すことによりループ・テスト式を評価するテスト式評価アクション2920に移行する。do whileループの場合、テストはループの本体のあとで評価される。最終テスト式が評価された後、または現行ループがdo whileループではない場合、論理流れ図2900による処理、したがって、ループ実行ユニットは終了する。ループ実行ユニットはループ本体の1回の実行だけをシミュレートする。終了すると、ループ実行ユニットは開始サイト制御に制御を返す。
switchユニットはswitchステートメントを処理する。switchユニットについては論理流れ図3000(第30a図、第30b図)に示す。switchユニットの処理は、switchテスト式を評価するテスト式評価アクション3002から始まる。switchテスト式は、式ユニットへの呼出しにより評価される。制御は、他のcaseラベルを検査しなければならないかどうか、ならびにチェックすべきcaseラベルが残っているかどうかを判定するチェックすべきcaseラベル判断3004に移転する。依然としてcaseラベルを検査する必要性があり、依然としてチェックすべきものが複数ある場合、処理は宣言ノード検索アクション3006(以下「アクション3006」という)に移行し、そうではない場合、処理はcase選択判断3028(以下「判断3028」という)に移行する。
アクション3006は、処理すべき次のcaseラベル用の宣言ノードを検索する。処理は、アクション3006から、caseラベルが記号テーブル内にあるかどうかを判定する記号テーブル内ラベル判断3008に移行する。caseラベルが記号テーブル内にある場合、処理はラベル集合構築アクション3012(以下「アクション3012」という)に移行する。そうではない場合、処理は、そのcaseラベルを記号テーブルに追加する記号テーブルへのラベル追加アクション3010(以下「アクション3010」という)に移行する。
アクション3010は、そのcaseラベルを表すための記号テーブル項目1300を作成する。新たに作成した記号テーブル項目1300は記号テーブルに格納される。処理は、アクション3010からアクション3012に移行する。アクション3012は、そのcaseラベルをラベル集合に格納し、検討したすべてのcaseラベルの集合を構築する。処理は、アクション3012から、case内の第1のステートメントを指すポインタの集合を構築するステートメント集合構築アクション3014に移行する。検討した各caseラベルごとに1つずつのポインタが存在する。ステートメント集合が更新された後、処理は式caseラベル同等判断3016(以下「判断3016」という)に移行する。
判断3016は、swichテスト式の結果とcaseラベルとを突き合わせる。switchテスト式の結果がcaseラベルと等しい場合、処理は現在のcase選択アクション3018(以下「アクション3018」という)に移行する。アクション3018は、現在のcaseラベルに対応するステートメントを実行すべきであることを示す。処理は、チェックすべきcaseラベルがこれ以上ないことを示すためにフラグを設定する調査停止記憶アクション3020(以下「アクション3020」という)に移行する。処理はアクション3020から判断3004に移行する。
switchテスト式の結果が現在のcaseラベルと等しくなかった場合、処理は、突合せが偽を返したかどうかを判定する突合せ結果偽判断3022に移行する。突合せが偽を返した場合、処理は、偽の突合せの数をカウントする偽caseカウント・アクション3024(以下「アクション3024」という)に移行する。switchテスト式の結果とcaseラベルが等しいことを判定できなかった場合、処理は、「不明」case集合構築アクション3026(以下「アクション3026」という)に移行する。アクション3026は、判断3016が結果を判定できなかったすべてのケースに対応するcaseラベルの集合に現在のcaseラベルを追加する。処理は、アクション3024およびアクション3026から判断3004に移行する。
case選択判断3028は、caseが選択されたかどうかを判定する。caseが選択された場合、処理は、次のbreakステートメントに到達するまで選択したcase内のステートメントを実行する次のbreakまでステートメントを実行するアクション3030に移行する。アクション1208を呼び出すことにより、ステートメントを実行する。case内のすべてのステートメントが実行されると、論理流れ図3000による処理、したがって、switchユニットは終了する。
caseがまだ選択されていない場合、処理は、偽caseの数がswitchステートメント内のcaseの数に等しいかどうかを判定する偽カウントcase数同等判断3032に移行する。偽caseの数がcaseの数に等しい場合、いずれのcaseラベルもswitchテスト式結果と一致しないことを意味し、処理はデフォルトcase内のステートメントを実行するデフォルトcase実行アクション3034(以下「アクション3034」という)に移行する。アクション1208を呼び出すことにより、ステートメントを実行する。アクション3034が完了すると、論理流れ図3000による処理、したがって、switchユニットは終了する。偽caseのカウントがswitchステートメント内のcaseの数に等しくない場合、処理は不明case判断3036(以下「判断3036」という)に至る。
判断3036は、「不明」caseの集合内にラベルがあるかどうかを判定する。「不明」case内にラベルがある場合、処理は不明caseとデフォルトcaseの選択アクション3038(以下「アクション3038」という)に移行する。そうではない場合、switchユニット内の処理は終了する。
アクション3038は、「不明」caseとデフォルトcaseとから実行すべきcaseを選択する。アクション3038は、CPH条件選択ユニット(第33図)を呼び出すことにより、どのcaseを選択するかを判定する。CPH条件選択ユニットについては以下に詳述する。処理は、アクション3038から、アクション3038で行った選択に基づいて情報を想定する情報想定アクション3040(以下「アクション3040」という)に移行する。アクション3040は、演算ユニットのアクション2734(第27図)と同様のものである。アクション3040は、vim想定ユニットを呼び出して、アクション3038で行った選択に基づいてモデル化メモリを更新する。
処理は、アクション3040から、次のbreakステートメントが検出されるまで選択したcase内のステートメントを実行するbreakまでのステートメント実行アクション3042に移行する。ステートメントは、アクション1208への呼出しにより実行される。ステートメントが実行された後、論理流れ図3000による処理、したがって、switchユニットは終了する。終了すると、switchユニットは開始サイト制御に処理制御を返す。
変数初期設定ユニットは、変数初期設定ステートメントを処理するものである。変数初期設定ユニットについては論理流れ図3100(第31図)として示す。変数初期設定ユニットの処理は、初期設定式を評価する初期設定評価アクション3102から始まる。初期設定式は、式ユニットを呼び出すことによって評価される。初期設定式が評価された後、処理は、代入された値を受け取る変数用の宣言ノードを突き止める、変数宣言ノード検出アクション3104(以下「アクション3104」という)に移行する。処理は、アクション3104から、演算ユニットを呼び出すことにより代入を評価する代入評価アクション3106に移行する。演算ユニットは代入演算子を指定して呼び出される。代入が評価された後、論理流れ図3100による処理、したがって、変数初期設定ユニットは終了する。
returnユニットはreturnステートメントを処理するものである。returnユニットについては論理流れ図3200(第32図)として示す。returnユニットは、returnステートメントが式を有するかどうかを判定するreturn式判断3202から処理を始める。returnステートメントがreturn式を有していない場合、処理は式評価アクション3204(以下「アクション3204」という)に移行する。そうではない場合、returnユニットは終了する。
アクション3204は、式ユニットを呼び出すことにより式を評価する。return式が評価された後、処理は、記号テーブル内の戻り値を探索する記号テーブル内の戻り値探索アクション3206(以下「アクション3206」という)に移行する。アクション3206は、戻り値に対応する記号テーブル項目1300からフィールド「記号位置」1306を検索する。処理は、return記号へのreturn式の代入を評価する代入評価アクション3208(以下「アクション3208」という)に移行する。アクション3208は、変数初期設定ユニットのアクション3106(第31図)と同様のものである。代入は、代入演算子を指定して演算ユニットを呼び出すことによって評価される。代入が評価された後、論理流れ図3200による処理、したがって、returnユニットは終了する。
ラベル・ユニットは、ステートメントを導入するラベルを処理するものである。ラベルとは、あとにコロン(「:」)が続く識別子である。「識別子」という用語は、Brian W.KernighanおよびDennis M.RitchieによるThe C Programming Language、179(Prentice−Hall、1978年)に定義されているように、ここで使用する。一実施形態のラベル・ユニットは、フロースルー処理を実行するだけであり、ラベル・ユニットは開始サイト制御に処理制御を移転する。
gotoユニットは、gotoステートメント内に指示されたステートメント(goto「ターゲット」ステートメント)に移行するように現行パスの制御の流れを方向付けるものである。gotoユニットは、前述のようにgotoパラメータを真に設定する。gotoユニットは、gotoターゲット・ステートメントを表す現行構文解析ツリー構造304内のノードを指すポインタを検索し、そのポインタを処理制御とともにアクション1208に転送する。制御がgotoユニットに戻ると、処理は終了し、gotoユニットは開始サイト制御に制御を移転する。本発明の一実施形態では、gotoユニットはルーチンによって実現される。マイクロフィッシュの付録Aの実施形態では、gotoユニット23は、「exe_goto_statement」というルーチンによって実現される。
仮想イメージ・オブジェクト708
仮想イメージ・オブジェクト708は、メモリ・モデルを構築、更新、および検査する。仮想イメージ・オブジェクト708は、4つのユニット、すなわちメモリ作成ユニット1500(前述)、活力(vim)プリミティブ試験ユニット、活力プリミティブ評価ユニット、および活力想定ユニットから構成される。仮想イメージ・オブジェクト708のこれら4つのユニットは、メモリ・モデルについての試験および操作を実行し、こうした試験および操作が活力プリミティブと呼ばれる。活力プリミティブは、メモリ・モデルの記憶された値に対して直接実行されるわけではなく、フェッチ値と呼ばれる記憶された値の検索したコピーに対して実行される。フェッチ値の使用は、値を操作する前にレジスタ中に置くコンピュータ・プログラムと類似している。活力プリミティブのある特定の使用についての情報は述語に集められる。述語は、後に自動モデル化に使用するためにログすることができる。活力プリミテイブ、フェッチ値、述語、プリミティブ評価ユニット、および想定ユニットについて、以下でさらに詳細に考察する。
本発明の1実施形態では、18個の別個の活力プリミティブがある。活力プリミティブは、true_as_condition、false_as_condition、initialized、valid_or_null_pointer、valid_pointer、invalid_pointer、valid_offset、comparable、incomparable、freeable、freed_memory、new_memory、non_zero、lost、int_to_float、float_to_int、state_eq、およびstate_neである。活力プリミティブ「true_as_condition」は、指定された位置が「真」であると評価されるかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「false_as_condition」は、指定された位置が「真」以外の値であると評価されるかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「initialized」は、指定された位置が初期値を含むかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブ「valid_or_null_pointer」は、指定された位置が、モデル化されたメモリの現在使用されている部分を指すポインタである有効ポインタ、または現在どこも指していない位置を指定するヌル・ポインタのいずれかを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「valid_pointer」は、指定された位置が、有効ポインタ、すなわちモデル化されたメモリの現在使用されている部分を指すポインタを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「invalid_pointer」は、指定された位置が、モデル化されたメモリの現在使用されている部分を指すポインタを含まないかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブ「valid_offset」は、指定された位置が、識別された構造またはアレイ中への有効オフセットを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「comparable」は、2つの位置が同じチャンク1700を指すかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「incomparable」は、2つの位置が同じチャンク1700を指さないかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「freeable」は、指定された位置が解放可能なメモリを含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「freed_memory」は、指定された位置を解放するよう活力ユニットに命令するものである。活力プリミティブ「new_memory」は、メモリ・モデル中で新しい位置を割り当てるよう活力ユニットに命令するものである。
活力プリミティブ「non_zero」は、指定された位置がゼロ定数以外の値を含むかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「lost」は、指定された位置が失われたメモリとしてマークされているかどうかを示すよう活力ユニットに命令するものである。活力プリミティブ「int_to_float」は、指定された位置の値を、整数表示から浮動小数点表示に変換するよう活力ユニットに命令するものである。活力プリミティブ「float_to_int」は、指定された位置の値を、浮動小数点表示から整数表示に変換するよう活力ユニットに命令するものである。活力プリミティブ「state_eq」は、指定された位置が、所与の状態と等しい状態にある資源を表すかどうかを示すよう活力ユニットに命令するものである。最後に、活力プリミティブ「state_ne」は、指定された位置が、所与の状態と等しくない状態にある資源を表すかどうかを示すよう活力ユニットに命令するものである。
活力プリミティブを評価する際にはしばしば、ある位置によってモデル化されたメモリのタイプの特定の特徴を理解することが必要となる。様々なタイプのモデル化されたメモリについては、「メモリ作成ユニット1500」の見出しで既に考察した。様々なタイプのモデル化されたメモリのそれぞれについて、対応するメモリ情報ブロック3400(第34図)が存在する。メモリ情報ブロック3400は、対応するメモリ・タイプの特定の特徴を識別する。メモリ情報ブロック3400は下記のフィールドを含む。「メモリ・タイプ」3402、「印刷可能メモリ名」3404、「定数フラグ」3406、「デリファレンス・タイプ」3408、「開始時初期化フラグ」3410、「開始時有効フラグ」3412、「ロスト・フラグ」3414、「自由許可フラグ」3416、「フリー・エラー・コード」3418、「資源フラグ」3420、「ログ試験フラグ」3422、「初期化」3424、「有効」3426、および「ヌル」3428。
フィールド「メモリ・タイプ」3402は、瞬間メモリ・タイプ情報ブロック3400(瞬間メモリ・タイプとも呼ばれる)が表すメモリのタイプを識別する。フィールド「印刷可能メモリ名」3404は、印刷可能なフォーマットの瞬間メモリ・タイプの名前を指定する。フィールド「印刷可能メモリ名」3404は、エラー・メッセージの生成に使用される。フラグ「定数フラグ」3406は、瞬間メモリ・タイプが定数であるときにオンにセットされる。メモリ・タイプが定数である場合には、そのタイプの位置は割当てを受けることができない。フィールド「デリファレンス・タイプ」3408は、適用可能であるときに、瞬間メモリ・タイプが指すメモリ・タイプを示す。
フラグ「開始時初期化フラグ」3410は瞬間メモリ・タイプが初期化されたときにオンにセットされる。フラグ「開始時有効フラグ」3412は、瞬間メモリ・タイプが有効ポインタであるときにオンにセットされる。フラグ「ロスト・フラグ」3414は、瞬間メモリ・タイプが失われる可能性があるときにオンにセットされる。フラグ「自由許可フラグ」3416は、瞬間メモリ・タイプを解放することができるときにオンにセットされる。フィールド「自由エラー・コード」3418は、適用可能である場合には、瞬間メモリ・タイプを解放する際に生成されるエラー・コードを指定する。
フラグ「資源フラグ」3420は、瞬間メモリ・タイプが資源を参照するときにオンにセットされる。フラグ「ログ試験フラグ」3422は、瞬間メモリ・タイプの位置に対して行われる試験をログしなければならないときにオンにセットされる。フィールド「初期化」3424は、ある位置を、初期化されたものであるとして瞬間メモリ・タイプから識別することができるかどうかを指定する。フィールド「有効」3426は、ある位置を、有効であるとして瞬間メモリ・タイプから識別することができるかどうかを指定する。フィールド「ヌル」3428は、ある位置を、ヌルであるものとして瞬間メモリ・タイプから識別することができるかどうかを指定する。
フェッチ値は、記憶された値に含まれる値の作業用コピーとして使用される。フェッチ値をフェッチ値ブロック3500で説明する。フェッチ値ブロック3500は、第35図に示してある。フェッチ値ブロック3500は下記のフィールドを含む。「バイト数」3502、「正確な値が既知のフラグ」3504、「正確値ポインタ」3506、「述語集合ポインタ」3508、「値の形式」3510、「実数の値」3512、「無符号整数の値」3514、「資源タイプ」3516、「資源状態」3518、「初期化フラグ」3520、「有効ポインタ」3522、「非ゼロ・フラグ」3524、「新規述語フラグ」3526、「変更フラグ」3528、「想定フラグ」3530、「svsポインタ」3532、「svsオフセット」3534、「位置からのフラグ」3536、「位置」3538、「チャンク起点」3540、「メモリ・タイプ」3542、「svサブセット・ポインタ」3544、「式ポインタ」3546、および「デリファレンス・フラグ」3548。
フィールド「バイト数」3502は、記述される値が表すバイト数を指定する。フラグ「正確な値が既知のフラグ」3504は、記述される値が完全に既知であるときにオンにセットされる。フィールド「正確値ポインタ」は、適用可能であるときに、正確な値を含むバイト・アレイを指す。指されるバイト・アレイのサイズは、フィールド「バイト数」3502に含まれる数と等しい。フィールド「述語集合ポインタ」3508は、瞬間フェッチ値に適用される全ての述語の集合を指す。フィールド「値の形式」3510は、記述される値の形式のタイプを示す。フィールド「実数の値」3512は、フィールド「値の形式」3510が実数値を示すときに、記述される値を実数形式で指定する。フィールド「無符号整数の値」3514は、フィールド「値の形式」3510が実数値以外を示すときに、記述される値を整数形式で指定する。
フィールド「資源タイプ」3516は、適用可能である場合には、記述される値に関連した資源のタイプを示す。フィールド「資源状態」3518は、適用可能である場合には、記述される値に関連した資源の状態を示す。フラグ「初期化フラグ」3520は、記述される値が初期化されたときにオンにセットされる。フィールド「有効ポインタ」3522は、フェッチ値が有効ポインタであるかどうかを示す。フラグ「非ゼロ・フラグ」3524は、真であるときには、フェッチ値がゼロ定数でないことを知らせる。フラグ「新規述語フラグ」3526は、「述語集合ポインタ」3508が指す述語の集合に、任意の述語が追加されているかどうかを示す。フラグ「変更フラグ」3528は、フェッチ値が任意の活力プリミティブによって変更されているかどうかを知らせる。フェッチ値は、活力プリミティブによって変更されているときには、メモリ・モデルに戻して記憶しなければならない。フラグ「想定フラグ」3530は、フェッチ値が活力プリミティブによって想定されているかどうかを示す。フェッチ値は、活力プリミティブによって想定されているときには、対応する記憶された値に上書きしなければならない。
フィールド「svsポインタ」3532は、フェッチ値の発生元となる、記憶された値のセットを指す。フィールド「svsオフセット」3534は、フィールド「svsポインタ」3532が指す記憶された値のセット中のフェッチ値の開始オフセットを含む。フラグ「位置からのフラグ」は、フェッチ値の内容がモデル化されたメモリの位置から来たものであるかどうかを示す。フィールド「位置」3538は、フェッチ値の発生元となるモデル化されたメモリ中の位置を指す。フィールド「チャンク起点」3540は、フィールド「svsポインタ」3532が指す記憶された値のセットを指すチャンク1700によって指される起点コンテキスト構造1600を指す。フィールド「メモリ・タイプ」3542は、どのような種類のメモリがフェッチ値によって使用されるかを指定する。
フィールド「svサブセット・ポインタ」3544は、フィールド「svsポインタ」3532が指す記憶された値のセットに含まれる記憶された値のサブセットを含む集合を指す。フィールド「式ポインタ」3546は、フェッチ値を含む式を表す現在の構文解析ツリー構造304中のノードを指すポインタを含む。フラグ「デリファレンス・フラグ」3548は、フェッチ値が実際に、フィールド「式ポインタ」3546が示す式中の値のデリファレンスであるかどうかを示す。
述語は、左側オペランドおよび場合によっては右側オペランドに適用される活力プリミティブの特定の適用についての情報を記憶している。述語は、述語ブロック3600で表される。述語ブロック3600は下記のフィールドを含む。「プリミティブ」3602、「無符号オペランド・フラグ」3604、「svsポインタ」3606、「svオフセット」3608、「svカウント」3610、「引数」3612、「引数オフセット」3614、「引数長さ」3616、「資源タイプ」3618、および「資源状態」3620。
フィールド「プリミティブ」3602は、この述語が記録する活力プリミティブのタイプを指定する。フラグ「無符号オペランド・フラグ」3604は、この述語が表す活力プリミティブ(表された活力プリミティブと呼ぶ)が無符号オペランドに適用されたかどうかを示す。フィールド「svsポインタ」3606は、表された活力プリミティブが適用される値に対応する記憶された値のセットを指す。フィールド「svオフセット」3608は、表された活力プリミティブが適用される、「svsポインタ」3606が指す記憶された値のセットの中の、第1の記憶された値のオフセットを指定する。フィールド「svカウント」3608は、表された活力プリミティブが適用される記憶された値の数を指定する。フィールド「引数」3612は、適用可能である場合には、述語の右側オペランドを指す。フィールド「引数オフセット」3614は、右側オペランドについての第1の記憶された値を指す。フィールド「引数長さ」3612は、右側オペランドを表すために使用される記憶された値の数を指定する。フィールド「資源タイプ」3618は、活力プリミティブが資源プリミティブであるときに、資源のタイプを示す。フィールド「資源状態」3620は、活力プリミティブが資源プリミティブであるときに、資源状態を示す。
活力プリミティブ試験ユニットは、メモリ・モデルの内容に対して試験を実行する。付録Dは、活力プリミティブ試験ユニットを実施するために使用される1実施形態の疑似コードを含む。活力プリミティブ評価ユニットは、メモリ・モデルを更新して、指定されたオペレーションを評価した結果を反映する。付録Dは、活力プリミティブ評価ユニットを実施するために使用される1実施形態の疑似コードを含む。活力想定ユニットは、メモリ・モデルを更新して、未解決な選択点をCPH選択条件ユニットで解決した結果を反映する。付録Dは、活力想定ユニットを実施するために使用される1実施形態の疑似コードを含む。
障害インジケータ・オブジェクト712
障害インジケータ・オブジェクト712は、障害インジケータ106を生成して、分析器202が検出したプログラミング・エラーを報告する。障害インジケータ・オブジェクト712の処理は、エラー生成ユニットによって実行される。エラー生成ユニットは、論理流れ図3700(第37図)として詳細に示してある。第37図の実施形態では、障害インジケータ106はエラー・メッセージの形になっている。
エラー生成ユニット中の処理は、検出されたプログラミング・エラーがメモリまたは資源の漏れであるかどうかを決定する漏れエラー判断3702(以下「判断3702」とする)から開始する。エラーが漏れである場合には、処理制御は、パス終了タイプを決定する処置3704(以下「処置3704」とする)に移ることになり、そうでない場合には、処理制御は、main関数中のローカル・エラーの判断3710(以下「判断3710」とする)に移る。
処置3704は、漏れを生じるパスがどのようにして終了したかを決定する。パスは3通りの方法、すなわち出口、ロングジャンプ、またはリターンの1つで終了することができる。パス終了のタイプが発見された後で、処理制御は、抑制終了タイプの判断3706(以下「判断3706」とする)に移る。判断3706は、構成オプションが、漏れを生じたパスの方法で、終了したパスの漏れエラーを抑制するようにセットされているかどうかを決定する。このような構成オプションがセットされている場合には、処理制御は、論理流れ図3700に従って処理を終了するリターン3708に移る。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。漏れエラーの報告を行う構成オプションは、「leaks_on_exit」、「leaks_on_longjump」、および「leaks_on_return」である。構成オプションについてのこれ以上の情報は、付録Bに与える。構成オプションが漏れエラー・メッセージを抑制するようにセットされていない場合には、処理は判断3710に移る。
判断3710は、現在の関数名が「main」であるかどうか、またこの関数が、「main」関数にローカルなメモリにポインタを戻しているかどうかを決定する。このような(判断3710が真であると決定した)場合には、処理は、論理流れ図3700に従って処理を終了するリターン3712に移る。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。判断3710が偽であると決定したときには、処理制御は、コンテキスト情報を得る処置3714(以下「処置3714」とする)に移る。
処置3714は、生成されたエラー・メッセージに記入するために使用することになるコンテキスト情報を収集する。コンテキスト情報により、ユーザは、コード中のプログラミング・エラーを突き止めることができる。処置3714は、障害のある関数を含むファイルのファイル名、および関数内のエラーが検出された行番号を決定する。処置3714は、エラーのある関数の名前、エラーが発生したパスの番号、およびエラーを含む式も収集する。関数のエミュレーション中にエラーが発生した場合には、処置3714は、エミュレートした関数の名前と、エミュレートした関数を含むファイルの名前と、エミュレートされた関数中のエラーが検出された行に対応するそのファイル中の行番号を収集する。処置3714でのデータ収集が完了した後で、処理は、構成オプション抑制判断3718(以下「判断3718」とする)に移る。
判断3718は、検出されたエラーの報告を防止する構成オプションが使用可能になっているかどうかを決定する。このような構成オプションが指定されている(判断3718が真であると決定した)ときには、処理は、リターン3720に移り、論理流れ図3700に従って処理を終了する。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。関連のある構成オプションは、特定のエラー・メッセージのみの生成を指示する「報告」、および特定のエラー・メッセージの抑制を指示する「抑制」である。特定の構成オプションについてのこれ以上の情報は、付録Bに与える。判断3718が偽であると決定したときには、処理制御は重複エラー判断3722(以下「判断3722」とする)に移る。
判断3722は、検出されたエラーが以前に報告されたエラーとの重複であるかどうかを決定する。エラーは、異なる3つの形で重複エラーに分類される。第1に、エラーは、以前のエラーが同じファイル名および文中に発生した場合に重複となる。第2に、エラーは、以前に報告されたミッシング・モデルについてのミッシング・モデル・エラーである場合に重複となる。第3に、エラーは、検出されたエラーを引き起こした記憶された値のセットが、以前に報告されたエラーを引き起こしたものと同じ記憶された値のセットである場合に重複となる。検出されたエラーが重複エラーである(判断3722が真であると決定した)場合には、処理は、リターン3724に移り、論理流れ図3700に従って処理を終了する。したがって、エラー生成ユニットは、エラー・メッセージを生み出すことなく終了する。判断3722が偽であると決定したときには、処理制御はエラー報告処置3726(以下「処置3726」とする)に移る。
処置3726は、検出されたエラーのタイプに対応するエラー・メッセージを印刷する。印刷する前に、エラー・メッセージには、処置3714で収集されたコンテキスト情報が記入される。エラー・メッセージが印刷された後で、論理流れ図3700による処理、したがってエラー生成ユニットは終了する。終了すると、エラー生成ユニットは、制御が発生したサイトに処理制御を戻す。
自動モデル化
概説
モデル118は、対応する関数の動作を概略的に表すものでる。モデル118は、関数の外部に可視の動作、すなわち関数の呼出し元に見える動作のみを含む。
別の関数を呼び出す関数を分析するときには、分析器202は、呼び出される関数のモデルを使用してその動作を決定する。これにより分析は非常に簡単になり、速度も上がり、分析器202は、呼び出される関数のソース・コードを必要としなくなり、その分析に時間をかける必要もなくなる。
モデルは、分析器202によって自動的に生成される。分析器は、関数を分析する際にその関数が何を行うかを記憶し、その関数の分析が完了するときに、その関数のモデル118を構築する。
分析器は、付録Gに記載する特殊なモデル化言語でモデル118を読み取り、これに書き込む。ユーザがその言語でモデル118に書き込むこともできるが、これは、ソースのない、したがって分析し、自動的にモデル化することができない関数について行われる。
モデル化の概念
エクスターン、制約、結果、アウトカム、および保護の5つの基本的なモデル化の概念がある。
エクスターンは、単なる外側から見ることのできる関数中の変数である。具体的に言うと、これらはパラメータ変数、大域変数、および静的変数である。モデル118は外部から可視の動作しかカプセル化しないので、これらはモデル118中に現れることができる変数のみとなる。
制約は、関数が入力されたときに真とならなければならない条件である。例えばそのパラメータの1つが有効ポインタであると関数が想定している場合には、関数のモデル118はそれを必要とする制約を含むことになる。制約は、関数が呼び出され、モデル118が評価されるときに試験されることになり、その制約が当てはまらない場合には、分析器202がエラーを報告することになる。
制約とは対照的に、結果は、関数が戻したときに真となる条件である。例えば関数がゼロを戻した場合には、それが結果になることになる。次いで結果は、分析器202で後続の分析に使用される。例えば、呼び出された関数の戻し値がその後で変数に割り当てられた場合には、呼び出された関数のモデル118が戻す結果は分析中の変数に割り当てられることになる。
アウトカムは、関数が分割されたケースである。ほとんどの関数は条件(if−then、switch、for loopなど)を含み、この条件付き実行はモデル118の中で表されなければならず、そうでなければ、モデル化されたあらゆる関数は呼び出されるたびに同じことを行うことになる。これに対して、モデル118はそれらがモデル化した関数より単純になる必要があり、そうでなければ、それらは関数自体より速く評価することができないことになる。関数は、それが戻す値に基づいてケースに分割され、これらの各ケースがアウトカムとなる。例えば関数mallocは、それが成功した場合にはポインタを、失敗した場合には0(ヌル)を、割り振られたメモリに戻す。mallocのモデルは2つのアウトカムを有する。より一般的には、分析器202は戻し値を以下のケースに分割する。
・関数が0を戻す
・関数が1を戻す
・関数が−1を戻す
・関数が上記3つのうちの1つに制限されない値を戻す
・戻し値が未知である
・関数が値を戻さない(ボイド関数の場合)
・関数がロングジャンプする
・関数が終了する
これらのアウトカム・タイプは、それらが速度(いくつかのアウトカム・タイプ)と情報の完全さ(多くのアウトカム・タイプ)の間の妥当なトレードオフを表すことから選択した。
モデルが複数のアウトカムを有するときには、分析器202は、どのアウトカムを使用するか選択しなければならない。この選択はしばしば入力値に基づいて行われる。保護は、こうした選択を表すために使用される機構である。例えば、以下の関数は、1を戻す場合と0を戻す場合の、2つのアウトカムを有する。
この関数は、パラメータが0である場合には1しか戻さず、パラメータが0でない場合には0しか戻さない。各アウトカムは適当な条件を具体化した保護を有することになる。
保護は制約と全く同じ形をしているが、それらの意味は異なる。制約は「このアウトカムが選択され、その制約の条件が当てはまらない場合に、エラーを報告する」という意味であるが、保護は、「その保護の条件が当てはまらない場合には、このアウトカムを選択してはならない」という意味となる。条件を評価することができない場合(例えば上記の値1が未知である場合)には、ある条件が想定され(ここではiの値)、あるアウトカムが選択される。
自動モデラ
自動モデラは、関数を分析する際にモデル118を構築する。現在の関数を介した各パスが終了するとき、処置1216中に、メモリ・モデル中の構造を走査し、制約および保護を決定する各外部について実行された試験と、結果を決定する各外部に対して行われた変更(割当てなど)とを決定する。これらの制約および結果はアウトカムにパッケージされる。現在の関数についての分析が終了するとき、処置1114内で、全ての個別のパスのアウトカムを操作し、無関係のオペレーションを除去し、重複したアウトカムを削除する。次いで個別のアウトカムを、エクスターンのリストと共に現在の関数のモデルにパッケージする。付録Eは、自動モデラを実施するために使用される一実施形態の擬似コードを含む。
マイクロフィッシュの付録Aのコンピュータ・プログラムは、一実施形態では、UNIX Solaris 2.5(R)オペレーティング・システムと、米国カリフォルニア州、Mountain ViewのSun Microsystemsから市販されているSun SPARCstationTM5などのワークステーションを備えたSPARCworksTM3.0.1コンパイラおよびリンカとを使用してコンパイルおよびリンクされた。第2の実施形態では、マイクロフィッシュの付録Aのコンピュータ・プログラムは、米国Washington州、RedmondのMicrosoft Corporationから市販されている、やはりMicrosoft Corporationから市販されているMicrosoft Windows NTTM3.5.1を使用してパーソナル・コンピュータ上で使用することができる、Microsoft Visual C++ 4.0が統合された開発環境を使用してコンパイルおよびリンクされた。このようなパーソナル・コンピュータとしては、米国サウスダコタ州、North Sioux CityのGateway 2000 Inc.から市販されているGateway G6−2000がある。マイクロフィッシュの付録Aのコンピュータ・プログラムが適合する特定のコンピュータ言語、およびマイクロフィッシュの付録Aのコンピュータ・プログラムによって規定されるコンピュータ・プロセスが実行されるコンピュータ・システムは、本発明の重要な面ではない。本発明の開示に鑑みて、当業者なら、様々なコンピュータ言語および/または様々なコンピュータ・システムを使用して本発明を実施することができる。
上記の記述は単なる例示であり、制限的なものではない。例えば、開示の実施形態ではCコンピュータ言語に従って関数を分析するが、本発明の原理は、上記のものも含めて、ただしそれらに制限されることなく、その他のコンピュータ命令プロトコルに適用することができる。本発明は下記の請求の範囲によってのみ制限される。
Claims (15)
- コンピュータ・システムにおいてプロセッサを使用し、少なくとも1つの関数を含むコンピュータ・プログラムを分析して、前記コンピュータ・システムが前記コンピュータ・プログラム中のプログラミング・エラーを自動的に検出することを可能にするコンピュータ実行方法であって、
前記コンピュータ・プログラムを、前記コンピュータ・プログラム内の演算子およびオペランドに対応するノードを含む構文解析ツリー構造に変換し、かつ前記コンピュータ・プログラムにより定義された全ての関数を取得する段階と、
前記取得された関数内のステートメントの列からなる制御フロー・パスをトラバースする段階であって、
前記関数用の構造メモリ・モデルを生成して記憶手段に保存する段階であって、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持する、構造メモリ・モデルを保存する段階、
前記構文解析ツリー構造内のノードを前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成する段階、
前記構造メモリ・モデルを使用して前記関数内のステートメントをシミュレートする段階、
前記関数内のステートメントのシミュレートが終了した後で、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれのポインタによっても指し示されないチャンクの検出を含む、プログラミング・エラーを検出する段階、および
検出された前記プログラミング・エラーを出力装置に出力する段階
を含み、
前記制御フロー・パスは、条件文または述語の値に基づいて分岐する選択点を含み、分析された制御フロー・パスを記録した選択点の履歴を使用して未処理の選択点が判断される方法。 - 前記出力する段階の後で、前記取得する段階で取得されたコンピュータ・プログラムによって規定される全ての前記関数を識別する段階と、
前記識別された関数を、関数呼出し順序に基づいて順序づけて、関数のリストを作成する段階と、
前記コンピュータ・プログラムによって規定される前記関数のリストの前記順序づけに基づいて、前記コンピュータ・プログラムの分析をスケジューリングする段階と
をさらに含む請求項1に記載の方法。 - 前記出力する段階の後で、入力装置から構成制御コマンドを受け入れる段階と、
前記構成制御コマンドに基づいて前記コンピュータ・プログラムの分析を修正する段階とをさらに含む請求項1に記載の方法。 - 前記入力装置から指定された関数用の第2構成制御コマンドを受け入れる段階と、
前記第2構成制御コマンドに基づいて前記の指定された関数の分析を修正する段階とをさらに含む請求項3に記載の方法。 - 前記入力装置から指定されたステートメント用の第3構成制御コマンドを受け入れる段階と、
前記第3構成制御コマンドに基づいて前記の指定されたステートメントの分析を修正する段階と
をさらに含む請求項4に記載の方法。 - 制御フロー・パスをトラバースする前記段階が、
前記制御フロー・パス中で前記未処理の選択点を識別する段階と、
前記未処理の選択点を、複数の分岐を含むツリー内のノードで表す段階と、
未選択の分岐を無作為に選択することにより、前記未処理の選択点を解決する段階と
をさらに含む請求項1に記載の方法。 - コンピュータ・システムにおいてプロセッサを使用し、1つまたは複数のステートメントを含むコンピュータ・プログラムを分析して、前記コンピュータ・システムが前記コンピュータ・プログラム中のプログラミング・エラーを自動的に検出することを可能にするコンピュータ実行方法であって、
前記コンピュータ・プログラムを検索して、条件文、述語および前記ステートメントの列を含む制御フロー・パスを取得する段階と、
前記取得された制御フロー・パスをトラバースする段階であって、
前記制御フロー・パス上の構造メモリ・モデルを記憶手段に保存する段階であって、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持する、構造メモリ・モデルを保存する段階、
前記コンピュータ・プログラムの変数名を、前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成する段階、
前記構造メモリ・モデルを使用して前記ステートメントをシミュレートする段階、
前記シミュレートが終了した後で、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれの変数によっても指し示されないチャンクの検出を含むプログラミング・エラーを検出する段階を含み、
前記シミュレートする段階において、前記制御フロー・パス内で分岐する選択点を履歴に記録し、前記トラバースする段階において、前記履歴を使用して未処理の選択点を判断する方法。 - 前記コンピュータ・プログラムは構文解析ツリー構造により表現される請求項7に記載の方法。
- 制御フロー・パスを前記コンピュータ・プログラムを通してトラバースする前記段階が、
前記制御フロー・パス中で前記未処理の選択点を識別する段階と、
前記未処理の選択点を、複数の分岐を含むツリー中のノードで表す段階と、
未選択の分岐を無作為に選択することにより、前記未処理の選択点を解決する段階と
をさらに含む請求項7に記載の方法。 - 前記未処理の選択点を解決する前記段階が、
前記選択点の履歴を保存する段階と、
第2の未処理の前記分岐を無作為に選択する段階とをさらに含む請求項9に記載の方法。 - 制御フロー・パスを前記コンピュータ・プログラムを通してトラバースする前記段階が、
前記構造メモリ・モデルを更新して、前記未処理の選択点を解決する前記段階を反映する段階をさらに含む請求項9に記載の方法。 - 前記コンピュータ・プログラムを分析して関数呼出しを識別する段階と、
前記関数呼出しに対応する呼び出された関数のデータ構造を見つける段階と、
前記関数呼出しに対応する呼び出された関数の前記データ構造を取り出す段階とをさらに含む請求項7に記載の方法であって、前記構造メモリ・モデルを使用して前記ステートメントをシミュレートする前記段階が、
前記関数呼出しに対応する呼び出された関数の前記データ構造を使用して前記関数呼出しを分析する段階をさらに含む方法。 - 前記構造メモリ・モデル中の前記プログラミング・エラーが、メモリの初期化されていない部分を知らせる請求項7に記載の方法。
- 実行可能コンピュータ・プログラム・コードを記憶するメモリと、前記メモリに機能的に結合されたプロセッサとを含むコンピュータ・システムであって、前記プロセッサは前記コンピュータ・プログラム・コードに含まれたコンピュータ実行可能命令に応答し、前記コンピュータ・プログラム・コードは前記メモリに格納されたコンピュータ・プログラム中のエラーを検出するためのエラー検出プロセッサのコンピュータ・プログラム・コードを含み、前記コンピュータ・プログラムは1つまたは複数のステートメントを含み、前記プロセッサは、前記エラー検出プロセッサのコンピュータ・プログラム・コードを実行する際、自動的に
前記コンピュータ・プログラム用の構造メモリ・モデルを生成して記憶手段に保存し、前記コンピュータ・プログラムは条件文、述語および前記ステートメントの列を含む制御フロー・パスを含み、前記構造メモリ・モデルは実行中に前記コンピュータ・プログラムにより使用されるチャンク・テーブル、チャンク、およびポインタによってまとめてリンクされた格納値を含み、前記チャンク・テーブルは前記チャンクを指すポインタを含み、前記チャンクは前記格納値のセットを指すポインタと、前記格納値の使用の有無を示すフラグとを含み、前記格納値のセットは前記格納値を指すポインタを保持し、
前記コンピュータ・プログラムの変数名を、前記構造メモリ・モデル内の位置を指すポインタと関連付けた記号テーブルを作成し、
前記エラー検出プロセッサのコンピュータ・プログラム・コードの少なくとも一部を含む分析エンジンを使用して、前記コンピュータ・プログラムを通じて前記構造メモリ・モデルを使用した前記制御フロー・パスのトラバースを実行し、
前記エラー検出プロセッサのプログラム・コードの少なくとも一部を含むステートメント・ユニットのプログラム・コードを実行して、前記制御フロー・パス内のステートメントをシミュレートし、さらに
前記制御フロー・パス内のステートメントのシミュレートが終了した後で、エラー生成ユニットのプログラム・コードを実行して、前記記号テーブル内のポインタにより指し示されるチャンク内の前記フラグの値を更新することにより、前記構造メモリ・モデル内で検出されたプログラミング・エラーを出力装置に出力し、前記プログラミング・エラーは、前記構造メモリ・モデルに割付けられているが、前記記号テーブル中のいずれの変数によっても指し示されないチャンクの検出を含み、
前記シミュレートにおいて、前記制御フロー・パス内で分岐する選択点を履歴に記録し、前記トラバースにおいて、前記履歴を使用して未処理の選択点を判断するコンピュータ・システム。 - 前記プロセッサは、前記エラー検出プロセッサのコンピュータ・プログラム・コードの実行中に、
前記エラー検出プロセッサのコンピュータ・プログラム・コードの少なくとも一部を含むオートモデラを使用して、無関係の動作および二重のパスの1つが削除されたデータ構造を生成することを特徴とする請求項14に記載のコンピュータ・システム。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US08/694,770 | 1996-08-07 | ||
US69477096A | 1996-08-13 | 1996-08-13 | |
PCT/US1997/014051 WO1998006019A2 (en) | 1996-08-07 | 1997-08-06 | Simulated program execution error detection method and apparatus |
Publications (3)
Publication Number | Publication Date |
---|---|
JP2002515996A JP2002515996A (ja) | 2002-05-28 |
JP2002515996A5 JP2002515996A5 (ja) | 2005-04-07 |
JP4633203B2 true JP4633203B2 (ja) | 2011-02-16 |
Family
ID=24790203
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
JP50825598A Expired - Lifetime JP4633203B2 (ja) | 1996-08-07 | 1997-08-06 | シミュレートされたプログラムの実行エラーの検出方法および装置 |
Country Status (3)
Country | Link |
---|---|
JP (1) | JP4633203B2 (ja) |
AU (1) | AU4058997A (ja) |
WO (1) | WO1998006019A2 (ja) |
Families Citing this family (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
AU3867500A (en) * | 1999-03-04 | 2000-09-21 | Origins Software Company | Automatic consistency checking of computer programs |
US8448139B2 (en) | 2009-10-05 | 2013-05-21 | International Business Machines Corporation | Automatic correction of application based on runtime behavior |
US9280406B2 (en) | 2009-10-05 | 2016-03-08 | International Business Machines Corporation | Automatic correction of application based on runtime behavior |
CN110489314B (zh) * | 2019-07-05 | 2022-07-12 | 中国平安人寿保险股份有限公司 | 模型异常检测方法、装置、计算机设备和存储介质 |
KR102491925B1 (ko) * | 2021-02-26 | 2023-01-26 | 고려대학교 산학협력단 | 프로그램 분석 장치 및 방법 |
KR102543663B1 (ko) * | 2021-07-29 | 2023-06-15 | 국방과학연구소 | 전자 장치의 소프트웨어 검증 방법 |
Family Cites Families (8)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JP2922723B2 (ja) * | 1992-06-29 | 1999-07-26 | キヤノン株式会社 | 情報処理装置 |
US5446900A (en) * | 1992-07-24 | 1995-08-29 | Microtec Research, Inc. | Method and apparatus for statement level debugging of a computer program |
US5325533A (en) * | 1993-06-28 | 1994-06-28 | Taligent, Inc. | Engineering system for modeling computer programs |
DE69415593T2 (de) * | 1993-06-30 | 1999-05-20 | Microsoft Corp | Verfahren zur Überprüfung eines nachrichtengesteuerten Betriebssystems |
US5590329A (en) * | 1994-02-04 | 1996-12-31 | Lucent Technologies Inc. | Method and apparatus for detecting memory access errors |
US5583988A (en) * | 1994-03-09 | 1996-12-10 | National Instruments Corporation | Method and apparatus for providing runtime checking features in a compiled programming development environment |
US5687375A (en) * | 1994-10-14 | 1997-11-11 | International Business Machines Corporation | Debugging of High Performance Fortran programs with backup breakpoints |
US5581696A (en) * | 1995-05-09 | 1996-12-03 | Parasoft Corporation | Method using a computer for automatically instrumenting a computer program for dynamic debugging |
-
1997
- 1997-08-06 AU AU40589/97A patent/AU4058997A/en not_active Abandoned
- 1997-08-06 JP JP50825598A patent/JP4633203B2/ja not_active Expired - Lifetime
- 1997-08-06 WO PCT/US1997/014051 patent/WO1998006019A2/en active Application Filing
Also Published As
Publication number | Publication date |
---|---|
JP2002515996A (ja) | 2002-05-28 |
WO1998006019A2 (en) | 1998-02-12 |
WO1998006019A3 (en) | 1998-03-26 |
AU4058997A (en) | 1998-02-25 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US5790778A (en) | Simulated program execution error detection method and apparatus | |
CA2637798C (en) | Computer process resource modelling method and apparatus | |
US6067641A (en) | Demand-based generation of symbolic information | |
Xie et al. | Saturn: A scalable framework for error detection using boolean satisfiability | |
US5812850A (en) | Object-oriented symbolic debugger using a compiler driven database and state modeling to control program execution | |
Lhoták et al. | Jedd: a BDD-based relational extension of Java | |
Kotik et al. | Automating software analysis and testing using a program transformation system | |
EP2141587A1 (en) | Method and system for generating of a control flow graph for representing a program code | |
Larsen et al. | Overture vdm-10 tool support: User guide | |
Sjölund | Tools and Methods for Analysis, Debugging, and Performance Improvement of Equation-Based Models | |
JP4633203B2 (ja) | シミュレートされたプログラムの実行エラーの検出方法および装置 | |
Sansom | Execution profiling for non-strict functional languages | |
Mayer et al. | Model-based debugging using multiple abstract models | |
Krauser Jr | Compiler-integrated software testing | |
Xie et al. | Improving generation of object-oriented test suites by avoiding redundant tests | |
Browne et al. | Visual programming and parallel computing | |
Fritzson et al. | OpenModelica System Documentation | |
Watson | Structured testing: Analysis and extensions | |
Walker | The implementation of an optimizing compiler for Icon | |
Chatterjee et al. | A low-level memory model and an accompanying reachability predicate | |
Parsa | Automatic Test Data Generation Symbolic and Concolic Executions | |
Belyaev et al. | Modeling of library functions in an industrial static code analyzer | |
Horváth | Static analyses for C++ in the presence of separate compilation | |
Makarov | An event-based language for programmable debugging | |
WO2005071534A2 (en) | A process for simulating and analysing an object-oriented code and the corresponding software product |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
A711 | Notification of change in applicant |
Free format text: JAPANESE INTERMEDIATE CODE: A712 Effective date: 20040706 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20040806 |
|
A621 | Written request for application examination |
Free format text: JAPANESE INTERMEDIATE CODE: A621 Effective date: 20040806 |
|
A131 | Notification of reasons for refusal |
Free format text: JAPANESE INTERMEDIATE CODE: A131 Effective date: 20070515 |
|
A601 | Written request for extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A601 Effective date: 20070814 |
|
A602 | Written permission of extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A602 Effective date: 20071001 |
|
A601 | Written request for extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A601 Effective date: 20071012 |
|
A602 | Written permission of extension of time |
Free format text: JAPANESE INTERMEDIATE CODE: A602 Effective date: 20071119 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20071115 |
|
A02 | Decision of refusal |
Free format text: JAPANESE INTERMEDIATE CODE: A02 Effective date: 20080415 |
|
RD13 | Notification of appointment of power of sub attorney |
Free format text: JAPANESE INTERMEDIATE CODE: A7433 Effective date: 20080715 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A821 Effective date: 20080715 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20080813 |
|
A911 | Transfer to examiner for re-examination before appeal (zenchi) |
Free format text: JAPANESE INTERMEDIATE CODE: A911 Effective date: 20080904 |
|
A912 | Re-examination (zenchi) completed and case transferred to appeal board |
Free format text: JAPANESE INTERMEDIATE CODE: A912 Effective date: 20081106 |
|
RD13 | Notification of appointment of power of sub attorney |
Free format text: JAPANESE INTERMEDIATE CODE: A7433 Effective date: 20100526 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A821 Effective date: 20100526 |
|
A521 | Request for written amendment filed |
Free format text: JAPANESE INTERMEDIATE CODE: A523 Effective date: 20101015 |
|
A01 | Written decision to grant a patent or to grant a registration (utility model) |
Free format text: JAPANESE INTERMEDIATE CODE: A01 |
|
A61 | First payment of annual fees (during grant procedure) |
Free format text: JAPANESE INTERMEDIATE CODE: A61 Effective date: 20101117 |
|
R150 | Certificate of patent or registration of utility model |
Free format text: JAPANESE INTERMEDIATE CODE: R150 |
|
FPAY | Renewal fee payment (event date is renewal date of database) |
Free format text: PAYMENT UNTIL: 20131126 Year of fee payment: 3 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
S111 | Request for change of ownership or part of ownership |
Free format text: JAPANESE INTERMEDIATE CODE: R313113 |
|
R350 | Written notification of registration of transfer |
Free format text: JAPANESE INTERMEDIATE CODE: R350 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
R250 | Receipt of annual fees |
Free format text: JAPANESE INTERMEDIATE CODE: R250 |
|
EXPY | Cancellation because of completion of term |