$ZTRAP (ObjectScript)
構文
$ZTRAP
$ZT
説明
$ZTRAP には、現在のエラー・トラップ・ハンドラの場所が含まれます。エラー・トラップ・ハンドラをコード化する方法の詳細は、"$ZTRAP でのエラー処理" を参照してください。
-
ルーチンでは、$ZTRAP はそのルーチンまたは他のルーチン内のラベルを参照できます。これには、ラベル名とルーチン名が含まれます。例えば、ルーチン MyRou 内の ラベル MyHandler に $ZTRAP を設定した場合、$ZTRAP 特殊変数には MyHandler^MyRou が含まれます。
-
プロシージャでは、$ZTRAP はそのプロシージャ内のラベルを参照する必要があります。これには、プロシージャ名からのラベルの行オフセットが含まれます。例えば、プロシージャ MyProc 内のプライベート・ラベル MyHandler に $ZTRAP を設定した場合、$ZTRAP 特殊変数には +17^MyProc が含まれます。
$ZTRAP を設定するには、次の 3 つの方法があります。
KILL $ZTRAP を実行することはできません。これを実行しようとすると、<SYNTAX> エラーになります。現在の $ZTRAP 値を削除するには、$ZTRAP="" を指定します。
Location
SET コマンドを使用することで、引用符付きの文字列として location を指定できます。
-
ルーチンでは、location は label (現在のルーチン内の行ラベル)、^routine (指定された外部ルーチンの開始)、または label^routine (指定された外部ルーチン内の指定されたラベル) として指定できます。プロシージャ内のラベルやプロシージャを参照する location をルーチンで指定しないでください。これは無効な location であり、InterSystems IRIS が $ZTRAP を実行しようとする際に実行時エラーになります。
-
プロシージャでは、label (そのプロシージャ・ブロック内のプライベート・ラベル) として location を指定できます。プロシージャ・ブロック内の $ZTRAP は、プロシージャ本体の外側にある location への移動には使用できません。プロシージャ・ブロック内の $ZTRAP は、プロシージャ・ブロック内の location しか参照できません。したがって、プロシージャでは、$ZTRAP を ^routine や label^routine に設定することはできません。設定しようとすると、<SYNTAX> エラーになります。
プロシージャでは $ZTRAP をプライベート・ラベル名に設定しますが、$ZTRAP 値はプライベート・ラベル名ではなく、プロシージャ・ラベル (プロシージャの先頭) からプライベート・ラベルの行の場所までのオフセットです。(例) +17^myproc。
$ZTRAP は、一部のコンテキスト (プロシージャ以外) で label+offset に対する従来のサポートを提供します。オプションのこの +offset は、label からオフセットする行数を指定する整数です。label は、同じルーチンに含める必要があります。+offset の使用は非推奨であり、コンパイル警告エラーが発生する場合があります。インターシステムズでは、location の指定時には行のオフセットを使用しないことを推奨します。
プロシージャまたは IRISSYS % ルーチンの呼び出し時における +offset の指定はできません。指定しようとすると、InterSystems IRIS は <NOLINE> エラーを発行します。
$ZTRAP の location は、現在のネームスペースにある必要があります。$ZTRAP では、拡張ルーチン参照をサポートしません。
存在しない行ラベル (現在のルーチンに存在しない location) を指定した場合、以下が発生します。
-
$ZTRAP の表示 : ルーチンでは、$ZTRAP には label^routine が含まれます。(例) DummyLabel^MyRou。プロシージャでは、$ZTRAP にはオフセットの最大許容値が含まれます。(例) +34463^MyProc。
-
$ZTRAP の呼び出し : InterSystems IRIS が <NOLINE> エラー・メッセージを返します。
各スタック・レベルは専用の$ZTRAP 値を備えることができます。$ZTRAP を設定すると、システムでは前回のスタック・レベルの $ZTRAP 値が保存されます。InterSystems IRIS では、現在のスタック・レベルが終了すると、この値がリストアされます。現在のスタック・レベルでエラー・トラップをオンにするには、エラー・トラップ・ハンドラの location を指定して、$ZTRAP にエラー・トラップ・ハンドラを設定します。次に例を示します。
IF $ZTRAP="" {WRITE !,"$ZTRAP not set" }
ELSE {WRITE !,"$ZTRAP already set: ",$ZTRAP
SET oldtrap=$ZTRAP }
SET $ZTRAP="Etrap1^Handler"
WRITE !,"$ZTRAP set to: ",$ZTRAP
// program code
SET $ZTRAP=oldtrap
WRITE !,"$ZTRAP restored to: ",$ZTRAP
エラーが発生すると、この形式ではコール・スタックが戻され、特定のエラー・トラップ・ハンドラに制御が移されます。
SqlComputeCode では、$ZTRAP=$ZTRAP を設定しないでください。これは、トランザクション処理およびエラー報告に関する重大な問題を引き起こす可能性があります。
エラー・トラップをオフにするには、$ZTRAP を NULL 文字列 ("") に設定します。これを行うと、現在 DO が実行されているスタック・レベルに設定されているエラー・トラップをクリアします。
$ZTRAP を使用してエラー・ハンドラを設定する場合、このハンドラは既存のどの $ETRAP エラー・ハンドラよりも優先されます。InterSystems IRIS は暗黙的に NEW $ETRAP コマンドを実行し、$ETRAP を NULL 文字列 ("") に設定します。
ターミナル・プロンプトからの $ZTRAP の使用は、現在のコード行に制限されます。SET $ZTRAP コマンドと、エラーを生成するコマンドは、コードの同じ行に含まれている必要があります。ターミナルは、各コマンド行の先頭で $ZTRAP をシステムの既定値にリストアします。
*Location
ルーチンでは、エラーが発生した後、コール・スタックをそのままにしておくこともできます。これを行うには、location の前および二重引用符内にアスタリスク (*) を挿入します。プロシージャ内でこの形式を使用することは有効ではありません。これを使用しようとすると、<SYNTAX> エラーになります。この例に示すように、プロシージャではないサブルーチンでのみ使用できます。
Main
SET $ZTRAP="*OnError"
WRITE !,"$ZTRAP set to: ",$ZTRAP
// program code
OnError
// Error handling code
QUIT
この形式では、$ZTRAP で指定した行ラベルへの GOTO が実行されるだけです。$STACK と $ESTACK は変更されません。$ZTRAP エラー処理ルーチンのコンテキスト・フレームは、エラーが発生したコンテキスト・フレームと同じです。ただし、InterSystems IRIS は $ROLES を、$ZTRAP が設定されていた実行レベルに有効であった値にリセットします。これにより $ZTRAP エラー・ハンドラは、エラー・ハンドラの設定後にルーチンに付与された上位特権を使用しないようにします。$ZTRAP エラー処理ルーチンが完了すると、スタックが前のコンテキスト・レベルに戻されます。この形式の $ZTRAP は特に、予期しないエラーの分析に便利です。
アスタリスクによって $ZTRAP オプションが設定されます。これは、location の一部ではありません。そのため、$ZTRAP で WRITE または ZZDUMP を実行しても、このアスタリスクは表示されません。
^%ETN
ルーチンでは、SET $ZTRAP="^%ETN" は、現在のエラー・トラップ・ハンドラとして、システムで提供されるエラー・ルーチン %ETN を設定します。%ETN は、これを呼び出したエラーの発生元であるコンテキストで実行されます。(%ET は %ETN の従来の名前です。これらの機能は同じですが、%ETN のほうが多少効率性に優れています)。エラー・ハンドラ ^%ETN は常に、* (アスタリスク) が先行しているかのように動作します。
プロシージャ・ブロック内の $ZTRAP は、プロシージャ本体の外側にある location への移動には使用できないため、プロシージャで SET $ZTRAP="^%ETN" を使用することはできません。使用しようとすると、<SYNTAX> エラーが返されます。
%ETN とそのエントリポイント FORE^%ETN、BACK^%ETN、および LOG^%ETN の詳細は、"(従来) ^%ETN を使用したエラー・ログ" を参照してください。
TRY / CATCH と $ZTRAP
TRY ブロック内で $ZTRAP を設定することはできません。これを試みると、コンパイル・エラーが生成されます。$ZTRAP は、TRY ブロックの前、または CATCH ブロック内で設定できます。
TRY ブロック内で発生したエラーは、$ZTRAP が以前に設定されているかどうかに関係なく、CATCH ブロックで処理されます。CATCH ブロック内で発生するエラーは、現在のエラー・トラップ・ハンドラによって処理されます。
以下の最初の例では、TRY ブロックで発生したエラーを示します。以下の 2 番目の例では、TRY ブロックにスローされた例外を示します。以下の両方の場合において、$ZTRAP ではなく、CATCH ブロックが用いられています。
SET $ZTRAP="Ztrap"
TRY { WRITE 1/0 } /* divide-by-zero error */
CATCH { WRITE "Catch taken" }
QUIT
Ztrap
WRITE "$ZTRAP taken"
SET $ZTRAP=""
QUIT
SET $ZTRAP="Ztrap"
TRY { SET myvar=##class(Sample.MyException).%New("Example Error",999,,errdatazero)
WRITE !,"Throwing an exception!",!
THROW myvar
QUIT }
CATCH { WRITE "Catch taken" }
QUIT
Ztrap
WRITE "$ZTRAP taken"
SET $ZTRAP=""
QUIT
ただし、TRY ブロックは $ZTRAP を設定および使用するコードを呼び出すことができます。以下の例では、0 による除算エラーが CATCH ブロックではなく、$ZTRAP によりキャッチされています。
TRY { DO Errsub }
CATCH { WRITE "Catch taken" }
QUIT
Errsub
SET $ZTRAP="Ztrap"
WRITE 1/0 /* divide-by-zero error */
QUIT
Ztrap
WRITE "$ZTRAP taken"
SET $ZTRAP=""
QUIT
CATCH ブロックからの THROW コマンドでも、$ZTRAP エラー・ハンドラを呼び出すことができます。
例
次の例では、$ZTRAP がこのプログラムの OnError ルーチンに設定されます。これによって、(数値を 0 で除算しようとすると) エラーが発生する SubA が呼び出されます。エラーが発生すると、$ZTRAP で指定した OnError ルーチンが呼び出されます。OnError は、$ZTRAP が設定されたコンテキスト・レベルで呼び出されます。OnError は Main と同じコンテキスト・レベルにあるため、実行は Main に戻りません。
Main
NEW $ESTACK
SET $ZTRAP="OnError"
WRITE !,"$ZTRAP set to: ",$ZTRAP
WRITE !,"Main $ESTACK= ",$ESTACK // 0
WRITE !,"Main $ECODE= ",$ECODE
DO SubA
WRITE !,"Returned from SubA" // not executed
WRITE !,"MainReturn $ECODE= ",$ECODE
QUIT
SubA
WRITE !,"SubA $ESTACK= ",$ESTACK // 1
WRITE !,6/0 // Error: division by zero
WRITE !,"fine with me"
QUIT
OnError
WRITE !,"OnError $ESTACK= ",$ESTACK // 0
WRITE !,"$ECODE= ",$ECODE
QUIT
次の例は、1 つの例外を除き、前の例と同じです。つまり、$ZTRAP location がアスタリスク (*) で始まっています。SubA でエラーが発生すると、このアスタリスクによって、($ZTRAP が設定された) Main のコンテキスト・レベルではなく、(エラーが発生した) SubA のコンテキスト・レベルで OnError ルーチンが呼び出されます。そのため、OnError が完了すると、DO コマンドに続く行で実行が Main に戻ります。
Main
NEW $ESTACK
SET $ZTRAP="*OnError"
WRITE !,"$ZTRAP set to: ",$ZTRAP
WRITE !,"Main $ESTACK= ",$ESTACK // 0
WRITE !,"Main $ECODE= ",$ECODE
DO SubA
WRITE !,"Returned from SubA" // executed
WRITE !,"MainReturn $ECODE= ",$ECODE
QUIT
SubA
WRITE !,"SubA $ESTACK= ",$ESTACK // 1
WRITE !,6/0 // Error: division by zero
WRITE !,"fine with me"
QUIT
OnError
WRITE !,"OnError $ESTACK= ",$ESTACK // 1
WRITE !,"$ECODE= ",$ECODE
QUIT