Skip to main content

(従来) 従来のエラー処理

ここでは、$ZTRAP を使用したエラー処理について説明します。これは、従来のアプリケーションで見られるエラー処理の形式です。新しいアプリケーションでは、代わりに TRY-CATCH を使用します。

従来のエラー処理の概要

InterSystems IRIS® データ・プラットフォームには、アプリケーションでエラー・ハンドラを使用して従来のエラー処理を実行できるようにするための機能が備わっています。エラー・ハンドラは、アプリケーションの実行中に発生するあらゆるエラーを処理します。エラー発生時に実行する ObjectScript コマンドは、特殊変数で指定します。これらのコマンドは、エラーを直接処理するか、エラーを処理するルーチンを呼び出します。

エラー・ハンドラの作成には、以下の基本的な処理を実行します。

  1. エラー処理を実行する 1 つ以上のルーチンを生成します。エラー処理を実行するコードを作成します。このコードは、アプリケーション全体に対する一般的なコードであっても、特定の処理における特定のエラー状態に対するものであってもかまいません。これにより、アプリケーションの特定個所で、カスタマイズされたエラー処理を実行できます。

  2. アプリケーション内に 1 つ以上のエラー・ハンドラを設定し、それぞれのエラー・ハンドラで固有の適切なエラー処理を使用します。

エラーが発生してもエラー・ハンドラが設定されていなかった場合の振る舞いは、その InterSystems IRIS セッションの開始方法によって異なります。

  1. ターミナル・プロンプトで InterSystems IRIS にサインオンし、エラー・トラップは設定していない場合、InterSystems IRIS は主デバイスにエラー・メッセージを表示し、プログラム・スタックの設定を変更せずにターミナル・プロンプトに戻ります。プログラマは、プログラムの実行を後で再開できます。

  2. アプリケーション・モードで InterSystems IRIS を実行し、エラー・トラップを設定していない場合、InterSystems IRIS は主デバイスにエラー・メッセージを表示し、HALT コマンドを実行します。

内部的なエラー・トラップの振る舞い

特殊変数 $ZTRAP (および $ETRAP) による InterSystems IRIS のエラー処理とその有効範囲を最大限に活用するには、InterSystems IRIS が制御をあるルーチンから別のルーチンに移す方法を理解すると役立ちます。

InterSystems IRIS は、以下のいずれかが発生するたびに、“コンテキスト・フレーム” というデータ構造を構築します。

  • ルーチンが DO コマンドで別のルーチンを呼び出す場合 (この種類のフレームは “DO フレーム” とも呼ばれます)。

  • XECUTE コマンド引数により、ObjectScript コードが実行される場合 (この種類のフレームは “XECUTE フレーム” とも呼ばれます)。

  • ユーザ定義関数を実行した場合

プロセスのアドレス部にあるプライベート・データ構造の 1 つ、コール・スタックにフレームが構築されます。InterSystems IRIS はルーチン用として、フレームに以下の要素を格納します。

  • $ZTRAP 特殊変数の値 (存在する場合)

  • $ETRAP 特殊変数の値 (存在する場合)

  • サブルーチンから返される位置情報

例えば、ルーチン A がルーチン B を DO ^B で呼び出すと、InterSystems IRIS は、コール・スタックに A のコンテキストを保持する DO フレームを構築します。また、ルーチン B がルーチン C を呼び出すと、コール・スタックに B のコンテキストを保持する DO フレームを追加します。

コール・スタックのフレーム
ルーチン A は、DO フレーム・コンテキスト ^A をコール・スタックに追加します。ルーチン A は DO ^B を呼び出します。ルーチン B は DO フレーム・コンテキスト ^B をコール・スタックに追加します。

上図のルーチン A がターミナル・プロンプトで DO コマンドを使用して呼び出される場合、図にはありませんが、追加の DO フレームがコール・スタックの一番下に存在しています。

現在のコンテキスト・レベル

現在のコンテキスト・レベルに関する情報を返すために以下を使用できます。

  • $STACK 特殊変数は、現在の相対スタック・レベルを含みます。

  • $ESTACK 特殊変数は、現在のスタック・レベルを含みます。任意のユーザ定義のポイントで、0 (レベル・ゼロ) に初期化できます。

  • $STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。

$STACK 特殊変数

$STACK 特殊変数は、プロセスのコール・スタックに現在保存されているフレームの数を含みます。$STACK 値は、基本的に、現在実行しているコンテキストの (ゼロ・ベースの) レベル番号です。したがって、イメージが開始されるとき、コマンドが処理されるまで、$STACK の値は 0 です。

詳細は、"ObjectScript リファレンス" の "$STACK" 特殊変数を参照してください。

$ESTACK 特殊変数

$ESTACK 特殊変数は、$STACK 特殊変数に類似していますが、NEW コマンドで変数を 0 にリセットできるため (また以前の値を保存できます)、エラー処理には $ESTACK の方が便利です。したがって、プロセスは、特定のコンテキストで $ESTACK をリセットし、$ESTACK レベル 0 のコンテキストとしてマークすることができます。その後エラーが発生した場合、エラー・ハンドラは $ESTACK 値をテストし、コール・スタックをそのコンテキストまで戻すことができます。

詳細は、"ObjectScript リファレンス" の "$ESTACK" 特殊変数を参照してください。

$STACK 関数

$STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。各コンテキストで、$STACK 関数は以下の情報を提供します。

  • コンテキスト・タイプ (DOXECUTE、ユーザ定義関数)

  • コンテキストで処理された最後のコマンドのエントリ参照とコマンド番号

  • コンテキストで処理された最後のコマンドを含むソース・ルーチン行あるいは XECUTE 文字列

  • コンテキストで発生した任意のエラーの $ECODE 値 ($ECODE が NULL でない場合、エラー処理中にのみ利用可能)

エラー発生時、すべてのコンテキスト情報はプロセス・エラー・スタックに即座に格納されます。その後、コンテキスト情報は、エラー・ハンドラが $ECODE 値をクリアするまで $STACK 関数によりアクセスできます。つまり、$ECODE 値が NULL でない場合、$STACK 関数は、エラー・スタックに保存されたコンテキストと同じ指定されたコンテキスト・レベルのアクティブなコンテキストではなく、エラー・スタックに保存されたコンテキストの情報を返します。

詳細は、"ObjectScript リファレンス" の "$STACK" 関数を参照してください。

エラーが発生し、エラー・スタックが既に存在している場合、InterSystems IRIS は、エラー・スタックの同じコンテキスト・レベルに別のエラーに関する情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているかどうかにかかわらず) エラー・スタックの次のレベルに配置されます。

したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。

$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。

エラー・コード

エラー発生時、InterSystems IRIS は $ZERROR 特殊変数と $ECODE 特殊変数に、エラーを示す値を設定します。$ZERROR および $ECODE の値は、エラーの直後に使用することを目的としています。これらの値は複数のルーチン呼び出しにわたっては保持されない可能性があるため、後で使用するために値を保持したい場合は、この値を変数にコピーする必要があります。

$ZERROR 値

InterSystems IRIS は、$ZERROR に以下を含む文字列を設定します。

  • 山括弧で囲まれた InterSystems IRIS のエラー・コード

  • エラー発生場所のラベル、オフセットおよびルーチン名

  • 一部のエラーでは、エラーの原因となった項目の名前などの追加情報

%Exception.SystemExceptionOpens in a new tab クラスの AsSystemError()Opens in a new tab メソッドは、$ZERROR と同じ形式で同じ値を返します。

以下の例では、InterSystems IRIS がエラーに遭遇した際に、$ZERROR に設定されるメッセージ・タイプを示します。以下の例では、未定義のローカル変数 abc が、ルーチン MyTest のラベル PrintResult より行オフセット 2 の位置で呼び出されます。$ZERROR は以下を含みます。

<UNDEFINED>PrintResult+2^MyTest *abc

存在しないクラスが行オフセット 3 の位置で実行されると、以下のエラーが発生します。

<CLASS DOES NOT EXIST>PrintResult+3^MyTest *%SYSTEM.XXQL

既存クラスの存在しないメソッドが行オフセット 4 の位置で実行されると、以下のエラーが発生します。

<METHOD DOES NOT EXIST>PrintResult+4^MyTest *BadMethod,%SYSTEM.SQL

128 文字までの任意の文字列として、特殊変数 $ZERROR を明示的に設定することもできます。以下はその例です。

 SET $ZERROR="Any String"

$ZERROR 値は、エラーの直後に使用することを目的としています。$ZERROR 値は複数のルーチン呼び出しにわたっては保持されない可能性があるため、後で使用するために $ZERROR 値を保持したいユーザはこの値を変数にコピーする必要があります。ユーザは $ZERROR を使用したらすぐに NULL 文字列 ("") に設定することを強くお勧めします。詳細は、"ObjectScript リファレンス" の "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。

$ECODE 値

エラー発生時、コンマに囲まれた文字列値を InterSystems IRIS は $ECODE に設定します。この値は、エラーに対応する ANSI 標準エラー・コードを含んでいます。例えば、未定義のグローバル変数を参照する場合、InterSystems IRIS は $ECODE セットに以下の文字列を設定します。

,M7,

エラーに対応 ANSI 標準エラー・コードを持たない場合、コンマに囲まれた文字列値 (文字 Z が先頭についた InterSystems IRIS エラー・コードが含まれる) に $ECODE を InterSystems IRIS は設定します。例えば、プロセスがシンボル・テーブルの領域をすべて使用した場合、InterSystems IRIS は $ZERROR 特殊変数にエラー・コード <STORE> を格納し、$ECODE に以下の文字列を設定します。

,ZSTORE,

エラー発生後、エラー・ハンドラは $ZERROR 特殊変数あるいは $ECODE 特殊変数を検証して、特定のエラー・コードをテストできます。

Note:

エラー・ハンドラは、特定のエラーに関し、$ECODE 特殊変数ではなく $ZERROR 特殊変数を検証する必要があります。

詳細は、"ObjectScript リファレンス" の "$ECODE" 特殊変数を参照してください。

$ZTRAP でのエラー処理

$ZTRAP でエラーを処理するには、$ZTRAP 特殊変数を location に設定し、引用符で囲まれた文字列として指定します。$ZTRAP 特殊変数はエントリ参照に対して設定します。このエントリ参照によって、エラー発生時における制御の移管先となる location を指定します。次にその場所に $ZTRAP コードを記述します。

$ZTRAP を空以外の値に設定すると、これは既存のどの $ETRAP エラー・ハンドラよりも優先されます。InterSystems IRIS は暗黙的に NEW $ETRAP コマンドを実行し、$ETRAP を "" に設定します。

プロシージャでの $ZTRAP の設定

プロシージャ内では、そのプロシージャ内の行ラベル (プライベート・ラベル) にのみ $ZTRAP 特殊変数を設定できます。プロシージャ・ブロック内から $ZTRAP を外部ルーチンに設定することはできません。

$ZTRAP 値を表示するとき、InterSystems IRIS はプライベート・ラベルの名前を返しません。代わりに、プロシージャの先頭からのそのプライベート・ラベルがある場所までのオフセットを返します。

詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。

ルーチンでの $ZTRAP の設定

ルーチン内では、$ZTRAP 特殊変数を現在のルーチンのラベル、外部ルーチン、または外部ルーチン内のラベルに設定できます。外部ルーチンを参照できるのは、そのルーチンがプロシージャ・ブロック・コードではない場合だけです。以下の例では、LogErr^ErrRou をエラー・ハンドラとして構築します。エラー発生時には、InterSystems IRIS が ^ErrRou ルーチン内の LogErr ラベルにあるコードを実行します。

  SET $ZTRAP="LogErr^ErrRou"

$ZTRAP 値を表示するとき、InterSystems IRIS はラベル名と (該当する場合には) ルーチン名を表示します。

ラベル名は最初の 31 文字内で一意である必要があります。ラベル名およびルーチン名では、大文字と小文字が区別されます。

ルーチン内では、$ZTRAP には 3 つの形式があります。

  • SET $ZTRAP="location"

  • SET $ZTRAP="*location"。この形式では、この関数を呼び出したエラーの発生元であるコンテキストで実行されます。

  • SET $ZTRAP="^%ETN" は、システムで提供されるエラー・ルーチン ^%ETN を実行します。このルーチンはルーチンを呼び出すエラーが発生したコンテキストにおいて実行されます。プロシージャ・ブロック内から ^%ETN (またはいずれかの外部ルーチン) を実行することはできません。コードが [Not ProcedureBlock] であることを指定するか、^%ETN エントリ・ポイント BACK^%ETN を呼び出す以下のようなルーチンを使用してください。

    ClassMethod MyTest() as %Status
      {
      SET $ZTRAP="Error"
      SET ans = 5/0      /* divide-by-zero error */
      WRITE "Exiting ##class(User.A).MyTest()",!
      QUIT ans
    Error
      SET err=$ZERROR
      SET $ZTRAP=""
      DO BACK^%ETN
      QUIT $$$ERROR($$$CacheError,err)
      } 
    

    ^%ETN とそのエントリ・ポイントの詳細は、"(従来) ^%ETN を使用したエラー・ログ" を参照してください。$ZTRAP と共に使用する際の処理の詳細は、"SET $ZTRAP=^%ETN" を参照してください。

詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。

$ZTRAP コードの記述

$ZTRAP が指し示す location はさまざまな操作を実行して、エラーを表示、ログ記録、または修正することができます。実行したいエラー処理操作の如何にかかわらず、$ZTRAP コードは以下の 2 つのタスクの実行により開始する必要があります。

  • $ZTRAP を他の値、すなわちエラー・ハンドラの location または空文字列 ("") のいずれかに設定します。(KILL $ZTRAP. とすることはできないので、SET を使用する必要があります。)これを行う理由は、エラー処理中に別のエラーが発生した場合において、そのエラーが現在の $ZTRAP エラー・ハンドラを呼び出してしまうためです。現在のエラー・ハンドラがユーザの関わるエラー・ハンドラである場合、無限ループとなってしまいます。

  • ある変数を $ZERROR に設定します。後でコード内で $ZERROR 値を参照する場合は、$ZERROR 自体ではなく、この変数を参照します。これを行う理由は、$ZERROR には最新のエラーが含まれているうえ、$ZERROR 値が、内部ルーチン呼び出しなどの複数のルーチン呼び出しにわたって保持されない可能性があるからです。エラー処理中に別のエラーが発生した場合、$ZERROR の値がその新しいエラーによって上書きされることになります。

    ユーザは $ZERROR を使用したらすぐに NULL 文字列 ("") に設定することを強くお勧めします。

以下の例では、これらの不可欠な $ZTRAP コード文を示します。

MyErrHandler
  SET $ZTRAP=""
  SET err=$ZERROR
  /* error handling code
     using err as the error
     to be handled */

$ZTRAP の使用法

アプリケーションの各ルーチンは、$ZTRAP を設定して、独自の $ZTRAP エラー・ハンドラを作成できます。エラー・トラップの発生時、InterSystems IRIS は以下の手順を実行します。

  1. 特殊変数 $ZERROR にエラー・メッセージを設定します。

  2. プログラム・スタックを、エラー・トラップが設定された時点 (SET $ZTRAP= の実行時) の状態にリセットします。つまり、システムは、エラー・トラップが設定された時点まで、スタックに存在するすべてのエントリを削除します。($ZTRAP がアスタリスク (*) で始まる文字列に設定されている場合、プログラム・スタックはリセットされません。)

  3. $ZTRAP の値により指定された位置でプログラムを再開します。$ZTRAP の値は保持されます。

    Note:

    $ZERROR 変数を、128 文字までの文字列として明示的に設定できます。通常、$ZERROR は NULL 文字列にのみ設定しますが、$ZERROR を値に設定してもかまいません。

エラー・トラップによる New コマンドの削除

エラー・トラップが発生しプログラム・スタック・エントリが削除されると、InterSystems IRIS は、スタックされたすべての NEW コマンドも削除し、SET $ZTRAP= を含むサブルーチン・レベルに戻します。しかし、NEW コマンドが $ZTRAP の設定前あるいは設定後にスタックに追加されたかどうかにかかわらず、そのサブルーチン・レベルで実行されたすべての NEW コマンドは維持されます。

以下に例を示します。

Main
  SET A=1,B=2,C=3,D=4,E=5,F=6
  NEW A,B
  SET $ZTRAP="ErrSub"
  NEW C,D
  DO Sub1
  RETURN
Sub1()
  NEW E,F
  WRITE 6/0    // Error: division by zero
  RETURN
ErrSub()
  WRITE !,"Error is: ",$ZERROR
  WRITE
  RETURN

Sub1 のエラーがエラー・トラップを起動した場合、Sub1 にスタックされた E と F における以前の値は削除されます。しかし、A、B、C、D はスタックされたままになります。

$ZTRAP フロー制御オプション

$ZTRAP エラー・ハンドラがエラー処理のために呼び出され、クリーンアップとエラー記録処理を実行した後、このエラー・ハンドラには 3 つのフロー制御オプションがあります。

  • エラーを処理し、アプリケーションを継続します。

  • 制御を別のエラー・ハンドラに渡します。

  • アプリケーションを終了します。

アプリケーションの継続

$ZTRAP がエラーを処理した後には、GOTO の発行によりアプリケーションを続行することができます。通常のアプリケーション処理を継続するために、$ZERROR または $ECODE 特殊変数値をクリアする必要はありません。しかし、$ZTRAP をクリアし (空の文字列を設定)、別のエラーが発生した際に無限のエラー処理ループに入らないようにする必要があります。詳細は、“エラー・ハンドラによるエラー処理” を参照してください。

エラー処理を実行した後、$ZTRAP エラー・ハンドラは GOTO コマンドを使用して、アプリケーション内で事前設定されたリスタートまたは継続ポイントに制御を移し、通常のアプリケーション処理を再開できます。

エラー・ハンドラがエラーを処理すると、$ZERROR 特殊変数が値に設定されます。エラー・ハンドラが処理を終了すると、この値は必ずしもクリアされるわけではありません。ルーチンによっては、$ZERROR を NULL 文字列に設定し直すものがあります。エラー・ハンドラを呼び出すエラーが次に発生したときに、$ZERROR は上書きされます。この理由から、$ZERROR 値はエラー・ハンドラのコンテキスト内でのみ使用する必要があります。この値を保持する場合は、これを変数にコピーして、$ZERROR 自体ではなくその変数を参照します。その他のコンテキストで $ZERROR を使用すると、信頼できる結果が生成されません。

別のエラー・ハンドラへの制御の移動

エラー条件を $ZTRAP エラー・ハンドラで修正できない場合、特殊な形式の ZTRAP コマンドを使用して、別のエラー・ハンドラに制御を移すことができます。 コマンド ZTRAP $ZERROR は、エラー条件を再度示し、エラー・ハンドラを使って、InterSystems IRIS で次のコール・スタック・レベルまでコール・スタックが戻るようにします。 InterSystems IRIS で次のエラー・ハンドラのレベルにコール・スタックを戻したら、そのエラー・ハンドラで処理が続行します。次のエラー・ハンドラは、$ZTRAP または $ETRAP で設定された可能性があります。

下図は、$ZTRAP エラー処理ルーチンのフロー制御を示しています。

$ZTRAP エラー・ハンドラ
A B C はそれぞれ SET $ZT to ^xERR を実行し、次の A、B、C を呼び出します。C は D を呼び出します。D はエラーとなり、最後の $ZT (CERR) を呼び出します。CERR ZTRAP $ZE は BERR を呼び出し

$ETRAP でのエラー処理

エラー・トラップの発生時に $ETRAP が設定されている場合、InterSystems IRIS は以下の手順を実行します。

  1. $ECODE および $ZERROR の値を設定します。

  2. $ETRAP の値であるコマンドを処理します。

既定で、DOXECUTE、またはユーザ定義の各関数コンテキストは、それを呼び出したフレームの $ETRAP エラー・ハンドラを継承します。つまり、どのコンテキスト・レベルであっても、指定された $ETRAP エラー・ハンドラが最終的に $ETRAP として定義されます。その定義が現在のレベルよりもいくつか低いスタック・レベルで行われていた場合でも同様です。

$ETRAP エラー・ハンドラ

$ETRAP 特殊変数には、エラーの発生時に実行される 1 つ以上の ObjectScript コマンドを含めることができます。SET コマンドを使用して、$ETRAP を、制御をエラー処理ルーチンに移す 1 つ以上の InterSystems IRIS コマンドを含む文字列に設定します。以下の例では、制御が LogError コード・ラベル (ルーチン ErrRoutine の一部) に移されます。

 SET $ETRAP="DO LogError^ErrRoutine"

$ETRAP 特殊変数内のコマンドの後ろには常に、暗黙の QUIT コマンドが続きます。引数付きの QUIT コマンドを必要とするユーザ定義の関数コンテキストで $ETRAP エラー・ハンドラが呼び出されると、暗黙の QUIT コマンドは NULL 文字列の引数で終了します。

$ETRAP はグローバル・スコープを持ちます。 これは、通常、$ETRAP の設定の前には NEW $ETRAP が必要であることを意味します。 そうしなければ、現在のコンテキストで $ETRAP の値が設定されている場合、その値がそのコンテキストの範囲を超えて渡された後、制御は上位レベルのコンテキストにあるのに、$ETRAP に格納された値は存在し続けることになります。 このため、NEW $ETRAP を指定しないと、$ETRAP が設定されたときのコンテキストがもう存在しない場合、$ETRAP が予期しないタイミングで実行される可能性があります。

詳細は、"ObjectScript リファレンス" の "$ETRAP" 特殊変数を参照してください。

コンテキスト固有の $ETRAP エラー・ハンドラ

以下の手順を実行することで、あらゆるコンテキストでコンテキスト固有の $ETRAP エラー・ハンドラを作成できます。

  1. NEW コマンドを使用して、$ETRAP の新しいコピーを作成します。

  2. $ETRAP を新しい値に設定します。

ルーチンで最初に $ETRAP の新しいコピーを作成せずに $ETRAP を設定すると、現在のコンテキスト、それを呼び出したコンテキスト、およびコール・スタックに保存されている可能性のあるその他のコンテキストに、新しい $ETRAP エラー・ハンドラが作成されます。このため、$ETRAP を設定する前に、その新しいコピーを作成することをお勧めします。

$ETRAP の新しいコピーを作成することで $ETRAP はクリアされないことに注意してください。$ETRAP の値は、NEW コマンドによって変更されないまま保持されます。

以下の図は、$ETRAP エラー・ハンドラのスタックを作成する $ETRAP 割り当てのシーケンスを示しています。この図が示している内容は次のとおりです。

  • ルーチン A は、$ETRAP の新しいコピーを作成して、それを “GOTO ^ERR” に設定し、ルーチン B を呼び出すための DO コマンドを含んでいます。

  • ルーチン B は、$ETRAP に対して何も行わず (その結果、ルーチン A の $ETRAP エラー・ハンドラを継承し)、ルーチン C を呼び出すための DO コマンドを含んでいます。

  • ルーチン C は $ETRAP の新しいコピーを作成して、それを “GOTO ^CERR” に設定し、ルーチン D を呼び出すための DO コマンドを含んでいます。

  • ルーチン D は、$ETRAP の新しいコピーを作成した後、それをクリアして、コンテキストに $ETRAP エラー・ハンドラを残しません。

ルーチン D でエラーが発生した場合 ($ETRAP エラー・ハンドラが定義されていないコンテキスト)、InterSystems IRIS はルーチン D の DO フレームをコール・スタックから削除して、制御をルーチン C の $ETRAP エラー・ハンドラに移します。ルーチン C の $ETRAP エラー・ハンドラはさらに ^CERR にディスパッチしてエラーが処理されます。ルーチン C でエラーが発生した場合、InterSystems IRIS は制御をルーチン C の $ETRAP エラー・ハンドラに移しますが、エラーが発生しているのは $ETRAP エラー・ハンドラが定義されているコンテキストであるため、スタックを戻すことはしません。

$ETRAP エラー・ハンドラ
generated description: errors etraphandlers

$ETRAP フロー制御オプション

$ETRAP エラー・ハンドラが、エラーを処理し、クリーンアップまたはエラー・ログ処理を実行するために呼び出された場合、次のフロー制御オプションがあります。

  • エラーを処理し、アプリケーションを継続します。

  • 制御を別のエラー・ハンドラに渡します。

  • アプリケーションを終了します。

エラーの処理とアプリケーションの継続

エラーを処理するために $ETRAP エラー・ハンドラが呼び出されると、InterSystems IRIS は、エラー状態が解除されるまでそのエラー状態がアクティブであると見なします。エラー状態を解除するには、$ECODE 特殊変数を NULL 文字列に設定します。

 SET $ECODE=""

$ECODE のクリアによって、プロセスのエラー・スタックもクリアされます。

エラー状態が解除されたら、通常は、GOTO コマンドを使用して、アプリケーションで事前設定されている再起動または継続のポイントに制御を移します。場合によっては、エラー状態の解除後に、終了して前のコンテキスト・レベルに戻る方が簡単なこともあります。

別のエラー・ハンドラへの制御の移動

エラー状態が解除されていない場合、$ETRAP エラー・ハンドラが呼び出されたコンテキストを QUIT コマンドが終了すると、InterSystems IRIS はコール・スタック上の別のエラー・ハンドラに制御を渡します。このため、$ECODE をクリアせずに、$ETRAP コンテキストから QUIT を実行することで、前のレベルのエラー・ハンドラに制御を渡すことができます。

ルーチン C から呼び出されたルーチン D に、制御を ^CERR に移すエラーが含まれる場合、前もって $ECODE が "" (空の文字列) に設定されていない ^CERR の QUIT コマンドは、前のコンテキスト・レベルの $ETRAP エラー・ハンドラに制御を移します。一方、$ECODE のクリアによってエラー状態が解除された場合、^CERRQUIT は、ルーチン B の DO ^C コマンドに続く文に制御を移します。

アプリケーションの終了

コール・スタックに前のレベルのエラー・ハンドラが存在しておらず、$ETRAP エラー・ハンドラがエラー状態を解除せずに QUIT を実行した場合、アプリケーションが終了します。アプリケーション・モードでは その後 InterSystems IRIS は停止し、制御がオペレーティング・システムに渡されます。それに続いて、ターミナル・プロンプトが表示されます。

エラー状態が解除されているかどうかにかかわらず、$ETRAP エラー・ハンドラのコンテキストを終了するには、QUIT コマンドを使用することに留意してください。引数なしの QUIT が必要なコンテキスト・レベルと引数ありの QUIT が必要なコンテキスト・レベル (ユーザ定義関数のコンテキスト) で、同じ $ETRAP エラー・ハンドラを呼び出すことができるため、特定のコンテキスト・レベルで必要とされる QUIT コマンド形式を示すために $QUIT 特殊変数が指定されます。

$QUIT 特殊変数は、引数ありの QUIT が必要なコンテキストの場合は 1 を返し、引数なしの QUIT が必要なコンテキストの場合は 0 を返します。

$ETRAP エラー・ハンドラは、$QUIT を使用することで、以下のようにどちらの状況にも対処できます。

  Quit:$QUIT "" Quit

該当する場合、$ETRAP エラー・ハンドラは、HALT コマンドを使用してアプリケーションを終了することができます。

エラー・ハンドラによるエラー処理

エラー・ハンドラでエラーが発生するとき、実行フローは、現在実行中のエラー・ハンドラ・タイプにより異なります。

$ZTRAP エラー・ハンドラでのエラー

$ZTRAP エラー・ハンドラで新規エラーが発生すると、InterSystems IRIS は、最初に検出したエラー・ハンドラに制御を渡し、必要に応じてコール・スタックを戻します。したがって、$ZTRAP エラーが現在のスタック・レベルで $ZTRAP をクリアせず、別のエラーが同じエラー・ハンドラで続けて発生した場合、$ZTRAP ハンドラが同じコンテキスト・レベルで再度呼び出されるため、無限ループの原因となります。これを回避するには、エラー・ハンドラの開始時点において $ZTRAP に他の値を設定します。

$ETRAP エラー・ハンドラでのエラー

$ETRAP エラー・ハンドラで新しいエラーが発生すると、InterSystems IRIS は、$ETRAP エラー・ハンドラが呼び出されたコンテキスト・レベルが削除されるまでコール・スタックを戻します。その後、InterSystems IRIS はコール・スタック上の次のエラー・ハンドラ (存在する場合) に制御を渡します。

$ZERROR 特殊変数と $ECODE 特殊変数のエラー情報

元のエラーの処理中に別のエラーが発生した場合、2 番目のエラー情報により、$ZERROR 特殊変数の最初のエラー情報が置き換えられます。しかし、InterSystems IRIS は、$ECODE 特殊変数に新規情報を追加します。2 番目のエラーのコンテキスト・レベルによっては、InterSystems IRIS は新しい情報をプロセス・エラー・スタックに追加する場合もあります。

$ECODE 特殊変数の既存の値が NULL 以外の場合、InterSystems IRIS は、新しいコンマ区切りの部分として、新規エラー・コードを現在の $ECODE 値に追加します。以下のいずれかの状況が発生するまで、$ECODE 特殊変数にエラー・コードが追加されます。

  • 以下のようにして、$ECODE を明示的にクリアします。

     SET $ECODE = ""
  • $ECODE の長さは、最大文字列長を超えています。

その後、次の新規エラー・コードにより、$ECODE にある現在のエラー・コード・リストが置き換えられます。

エラーが発生し、エラー・スタックが既に存在している場合、InterSystems IRIS は、エラー・スタックの同じコンテキスト・レベルに別のエラーに関する情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているかどうかにかかわらず) エラー・スタックの次のレベルに配置されます。

したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。

$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。

詳細は、"ObjectScript リファレンス" の "$ECODE" 特殊変数と "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。

強制エラー

$ECODE 特殊変数を設定、あるいは ZTRAP コマンドを使用して、制御環境でエラーを発生させます。

$ECODE の設定

$ECODE 特殊変数に NULL 以外の文字列を設定し、エラーを発生させることができます。ルーチンで $ECODE に NULL 以外の文字列を設定すると、InterSystems IRIS は $ECODE に特定の文字列を設定し、その後、エラー状態を生成します。この状況で $ZERROR 特殊変数は、以下のエラー・テキストと共に設定されます。

<ECODETRAP>

その後、通常のアプリケーション・エラーのように、エラー・ハンドラに制御を渡します。

エラー・ハンドラにロジックを追加し、$ECODE の設定により発生させるエラーをチェックできます。エラー・ハンドラは、<ECODETRAP> エラー (例えば、“$ZE["ECODETRAP"” に対して $ZERROR をチェックするか、または選択する特定の文字列値に対して $ECODE をチェックできます。

アプリケーション固有エラーの生成

$ECODE の ANSI 標準フォーマットは、1 つ以上のコンマに囲まれたエラー・コードのリストです。

  • 接頭語 “Z” 付きのエラーは、実装固有のエラーです。

  • 接頭語 “U” 付きのエラーは、アプリケーション固有のエラーです。

エラー・ハンドラで $ECODE に接頭語 “U” を持つ適切なエラー・メッセージを設定し、ANSI 標準に合う独自のエラー・コードを生成できます。

  SET $ECODE=",Upassword expired,"

ターミナル・プロンプトでのエラー処理

エラー・ハンドラ・セットを持たないターミナル・プロンプトで InterSystems IRIS にサインオンした後エラーを生成する場合、InterSystems IRIS は、入力したコード行でエラーが発生すると、以下の手順を実行します。

  1. InterSystems IRIS は、プロセスの主デバイスで、エラー・メッセージを表示します。

  2. エラーが発生したコール・スタック・レベルでプロセスを中断します。

  3. プロセスをターミナル・プロンプトに戻します。

エラー・メッセージ形式の理解

エラー・メッセージとして、InterSystems IRIS は以下の 3 行を表示します。

  1. エラーが発生したすべてのソース・コード行

  2. ソース・コードの行の下で、エラーが発生したコマンドを指定するキャレット (^)

  3. $ZERROR のコンテンツを含む行

以下のターミナル・プロンプトの例では、2 番目の SET コマンドに未定義のローカル変数エラーがあります。

USER>WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
hello

WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
                              ^
<UNDEFINED> *zzz
USER>

以下の例では、ターミナル・プロンプトから実行される mytest という名前のプログラムにコードと同じ行があります。

USER>DO ^mytest
hello

  WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
                                ^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>

この場合、$ZERROR は、mytest の中で WriteOut という名前のラベルから 2 行のオフセット位置でエラーが発生したことを示しています。プロンプトが変更され、新規のプログラム・スタック・レベルが開始されたことを示している点に注意してください。

ターミナル・プロンプトの理解

既定で、ターミナル・プロンプトは現在のネームスペース名を示します。トランザクションが 1 つ以上開いている場合、$TLEVEL トランザクション・レベル・カウントも含まれます。ZNSPACE コマンドの説明に従って、既定のプロンプトを異なる内容で構成することができます。以下の例は、それらの既定の設定を示します。

USER>
TL1:USER>

ルーチンの実行中にエラーが発生すると、システムは、現在のプログラム・スタックを保存して、新規スタック・フレームを開始します。以下のような拡張プロンプトが表示されます。

USER 2d0>

この拡張プロンプトは、プログラム・スタックに 2 つのエントリがあり、その最後の方が DO (d で示されています) の呼び出しであることを示しています。このエラーにより、プログラム・スタックに 2 つのエントリが置かれることに注意してください。次の DO 実行エラーにより、以下のプロンプト結果となります。

USER 4d0>

説明の詳細は、“コマンド行ルーチンのデバッグ” の章の "ターミナル・プロンプトのプログラム・スタック情報表示" を参照してください。

エラーのリカバリ

以下のいずれかの手順を実行できます。

  • ターミナル・プロンプトからコマンドを発行します。

  • 変数とグローバル・データを表示、修正します。

  • エラーと他のルーチンを含むルーチンを編集します。

  • 他のルーチンを実行します。

これらの手順により、別のエラーを発生させる可能性もあります。

これらの手順の実行後、実行を再開する、あるいはプログラム・スタックの一部/すべてを削除することをお勧めします。

次に続くコマンドでの実行の再開

ターミナル・プロンプトから引数なしの GOTO を入力すれば、エラーを引き起こしたコマンドの次のコマンドで実行を再開できます。

USER>DO ^mytest
hello

  WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
                                ^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>GOTO
world

USER>

別の行での実行の再開

ターミナル・プロンプトからラベル引数付きの GOTO を発行すると、別の行で実行を再開できます。

USER 2d0>GOTO ErrSect

プログラム・スタックの削除

ターミナル・プロンプトから引数なしの QUIT コマンドを発行すると、プログラム・スタック全体を削除できます。

USER 4d0>QUIT
USER>

プログラム・スタックの部分削除

ターミナル・プロンプトから整数の引数付きの QUIT n コマンドを発行すると、最後の (または最後にある複数の) プログラム・スタック・エントリを削除できます。

USER 8d0>QUIT 1
 
USER 7E0>QUIT 3
 
USER 4d0>QUIT 1
 
USER 3E0>QUIT 1
 
USER 2d0>QUIT 1
 
USER 1S0>QUIT 1
 
USER>

この例では、プログラム・エラーによって 2 つのプログラム・スタック・エントリが作成されているので、GOTO を発行して実行を再開するには、“d” スタック・エントリに移動している必要があります。他に発生する内容に応じて、“d” スタック・エントリは偶数 (USER 2d0>) または奇数 (USER 3d0>) となります。

NEW $ESTACK を使用すれば、指定のプログラム・スタック・レベルで終了できます。

USER 4d0>NEW $ESTACK

USER 5E1>
/* more errors create more stack frames */

USER 11d7>QUIT $ESTACK
 
USER 4d0>

NEW $ESTACK コマンドにて、エントリが 1 つプログラム・スタックに追加されます。

FeedbackOpens in a new tab