Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

TRY

実行中のエラーを監視するコード・ブロックを指定します。

Synopsis

TRY {
   . . .
}

説明

TRY コマンドは引数を取りません。中括弧で囲まれた ObjectScript コード文のブロックを識別するために使用されます。このコード・ブロックは、構造化された例外処理のための保護されたコードです。このコード・ブロック内で例外が発生した場合、Caché は $ZERROR$ECODE を設定し、CATCH コマンドによって識別される、例外ハンドラに実行を移します。

例外は、0 による除算の試みなどの実行時エラーの結果として発生する場合があります。また例外は、THROW コマンドの発行により明示的に伝達されない場合があります。エラーが発生しなかった場合、CATCH コード・ブロックの後の次の ObjectScript 文で実行を続けます。

CATCH ブロックのすぐ後に、TRY ブロックが続く必要があります。TRY コード・ブロックと CATCH コマンドの閉じ中括弧の間に、実行可能コード文またはラベルを指定できません。しかし、TRY ブロックとその CATCH ブロックの間にコメントを指定できます。CATCH ブロックは 1 つのみが、各 TRY ブロックに対して許可されます。ただし、以下のようにペアになった TRY/CATCH ブロックを入れ子にすることはできます。

  TRY {
       /* TRY code */
       TRY {
           /* nested TRY code */
       }
       CATCH {
          /* nested CATCH code */
       }
  }
  CATCH {
      /* CATCH code */
  }

通常、ObjectScript プログラムは、複数の TRY ブロックで構成され、各 TRY ブロックのすぐ後に、関連付けられた CATCH ブロックが続きます。

QUIT および RETURN

TRY ブロックは、QUIT または RETURN を使用して終了できます。QUIT は、現在のブロック構造を終了し、ブロック構造の外側にある次のコマンドで実行を続けます。たとえば、入れ子の TRY ブロック内で QUIT を発行すると、TRY ブロックを終了して囲んでいるブロック構造に移動します。TRY ブロック内で QUIT コマンドを発行すると、対応する CATCH ブロックの後の最初のコード行に実行を移します。引数付きの QUIT を使用して、TRY ブロックを終了することはできません。これを行うと、コンパイル・エラーが返されます。TRY ブロック内からルーチンを完全に終了するには、RETURN 文を発行します。

TRY ブロックの QUIT または RETURN コマンドで例外が生成される場合がまれにあります。これは、TRY が新しいコンテキストを作成してから、古いコンテキストの一部を削除した場合に起こる可能性があります。古いコンテキストに戻そうとすると、例外が発生します。TRY ブロックの QUIT または RETURN の例外は、CATCH ブロックの例外ハンドラを呼び出しません。

$ZTRAP および $ETRAP

TRY コマンドと CATCH コマンドは実行レベル内でエラー処理を行います。TRY ブロック内で例外が発生すると、Caché は通常、TRY ブロックの直後に続く例外処理コードの CATCH ブロックを実行します。これは 推奨されるエラー処理動作です。

TRY ブロック内で $ZTRAP および $ETRAP を設定することはできません。ただし、TRY ブロック内の引数なしの DO ブロック内で $ZTRAP または $ETRAP を設定することはできます。これは、DO ブロックの行が独自の実行レベルにあり、独自のエラー・ハンドラを持つためです。

TRY ブロックに入る前に $ZTRAP が設定されていて、例外が TRY ブロック内で発生する場合、Caché は、$ZTRAP ではなく CATCH ブロックを取得します。

TRY ブロックに入る前に $ETRAP が設定されていて、例外が TRY ブロック内で発生する場合、Caché は、 未然に阻止しない限り、CATCH ではなく $ETRAP を取得する可能性があります。例外の発生時に $ETRAPCATCH が両方とも存在している場合、現在の実行レベルに適用されるエラー・コード (CATCH または $ETRAP) が実行されます。$ETRAP はもともと、実行レベルに関連付けられていないため、Caché では、別に指定されない限り、現在の実行レベルに関連付けられると想定されます。$ETRAP を設定して $ETRAP のレベル・マーカーを作成する前に、NEW $ETRAP を実行する必要があります。この結果、Caché は、$ETRAP ではなく、CATCH を現在のレベルの例外ハンドラとして正しく処理することができます。そうでない場合は、システム・エラー (THROW コマンドによってスローされたシステム・エラーなど) が $ETRAP 実行ハンドラを取得する可能性があります。

GOTO および DO

GOTO または DO コマンドを使用して、TRY ブロック内のラベルで TRY ブロックに入ることができます。後から TRY ブロック内で例外が発生する場合、TRY キーワードで TRY ブロックに入ったかのように、CATCH ブロックの例外ハンドラが取得されます。ただし、コーディングをわかりやすくするために、GOTODO を使用して TRY ブロックに入ることは避けてください。

もちろん、TRY ブロック内または CATCH ブロック内から GOTO を発行できます。

GOTODO を使用して CATCH ブロックに入ることはお勧めしません。

TRY ブロック内での DO

TRY 文を使用すると、THROW によって、フレーム・スタックの検索が、適切な CATCH ブロックを検出しようとします。フレーム・スタックが TRY ブロック内での実行を示すと、対応する CATCH ブロックで実行が再開します。ただし、Caché は、CATCH ブロックを実行する前に、現在の TRY ブロック内で任意の "ローカル" 呼び出しを削除する必要があります。

TRY ブロックに DO 文が含まれていて、その TRY ブロックに再度入る結果になる場合、次の 2 つのうちのいずれかが発生します。

“ローカル” DO 呼び出し (現在の TRY ブロック内に留まる DO 呼び出し) : 前のフレーム・スタック・エントリが、同じ TRY ブロックにある DO 呼び出しの場合、その DO は、現在の TRY ブロック内の "ローカル" サブルーチン呼び出しと見なされます。この場合、CATCH にはすぐには入らず、フレーム・スタックがポップされ (場合によっては、最近割り当てられた NEW 変数が削除され)、現在の TRY ブロックでの DO 呼び出しで検索が再開します。新しい前のフレーム・スタック・エントリが、現在の TRY ブロック内からの DO でない場合、対応する CATCH ブロックに入ります。ただし、前のフレーム・スタック・エントリが同じ TRY の別の DO の場合、フレーム・スタックは (最近割り当てられた NEW 変数と共に) 再びポップされます。この動作は、前のフレーム・スタック・エントリが DO でなくなるまで継続され、その時点で CATCH ブロックに入ります。

“反復” DO 呼び出し (TRY ブロックから出るが、後の実行でその TRY ブロックに再度入る TRY ブロック内の DO 呼び出し) : CATCH ブロックを検索しているときに、前のフレーム・スタック・エントリが現在の TRY ブロック内の DO だが、その前のスタック・フレームのターゲット・ラベルが現在の TRY ブロック内 (入れ子にされた TRY ブロックを含む) にない場合、フレーム・スタックはポップされず (また、最近割り当てられたローカル変数がポップされず)、CATCH ブロックにすぐに入ります。この CATCH ブロックが別の THROW を実行すると、反復 DO フレームが依然としてフレーム・スタック上にあるため、現在の CATCH ブロックに再度入る可能性があります。

このセクションの例は、実行時エラー (%Exception.SystemExceptionOpens in a new tab エラー) を示しています。THROW を発行することで呼び出されたユーザ指定の例外の例は、THROW および CATCH コマンドを参照してください。

以下の例では、TRY コード・ブロックが実行されます。ローカル変数 a を設定しようとします。最初の例では、コードが正常に完了し、CATCH はスキップされます。2 番目の例では、<UNDEFINED> エラーでコードが失敗し、CATCH の例外ハンドラに実行が渡されます。

TRY が成功します。CATCH ブロックがスキップされます。実行が 2 番目の TRY ブロックで継続します。

  TRY {
    WRITE "1st TRY block",!
    SET x="fred"
    WRITE "x is a defined variable",!
    SET a=x
  }
  CATCH exp
  {
     WRITE !,"This is the CATCH exception handler",!
      IF 1=exp.%IsA("%Exception.SystemException") {
         WRITE "System exception",!
         WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
         WRITE "Location: ",exp.Location,!
         WRITE "Code: ",exp.Code,!
         WRITE "Data: ",exp.Data,!!
      }
      ELSE { WRITE "not a system exception",!!}
      WRITE "$ZERROR: ",$ZERROR,!
      WRITE "$ECODE: ",$ECODE
      RETURN
  }
  TRY {
    WRITE !,"2nd TRY block",!
    WRITE "This is where the code falls through",!
    WRITE "$ZERROR: ",$ZERROR,!
    WRITE "$ECODE: ",$ECODE
  }
  CATCH exp2 {
    WRITE !,"This is the 2nd CATCH exception handler",!
  }

TRY が失敗します。実行が CATCH ブロックで継続します。CATCH ブロックが RETURN で終了するため、2 番目の TRY ブロックは実行されません。

  TRY {
    WRITE "1st TRY block",!
    KILL x
    WRITE "x is an undefined variable",!
    SET a=x
  }
  CATCH exp {
      WRITE !,"This is the CATCH exception handler",!
      IF 1=exp.%IsA("%Exception.SystemException") {
         WRITE "System exception",!
         WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
         WRITE "Location: ",exp.Location,!
         WRITE "Code: ",exp.Code,!
         WRITE "Data: ",exp.Data,!!
      }
      ELSE { WRITE "not a system exception",!!}
      WRITE "$ZERROR: ",$ZERROR,!
      WRITE "$ECODE: ",$ECODE
      RETURN
  }
  TRY {
    WRITE !,"2nd TRY block",!
    WRITE "This is where the code falls through",!
    WRITE "$ZERROR: ",$ZERROR,!
    WRITE "$ECODE: ",$ECODE
  }
  CATCH exp2 {
    WRITE !,"This is the 2nd CATCH exception handler",!
  }

TRY が終了します。以下の例では、TRY ブロックの実行がエラーではなく QUIT または RETURN のいずれかによって終了されるため、CATCH ブロックは実行されません。RETURN の場合、プログラムの実行が停止します。QUIT の場合、プログラムの実行は 2 番目の TRY ブロックで継続します。

  TRY {
    WRITE "1st TRY block",!
    KILL x
    WRITE "x is an undefined variable",!
    SET decide=$RANDOM(2)
    IF decide=0 { WRITE "issued a QUIT",!
                  QUIT }
    IF decide=1 { WRITE "issued a RETURN",!
                  RETURN }
    WRITE "This should never display",!
    SET a=x
  }
  CATCH exp {
      WRITE !,"This is the CATCH exception handler",!
      IF 1=exp.%IsA("%Exception.SystemException") {
         WRITE "System exception",!
         WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),!
         WRITE "Location: ",exp.Location,!
         WRITE "Code: ",exp.Code,!
         WRITE "Data: ",exp.Data,!!
      }
      ELSE { WRITE "not a system exception",!!}
      WRITE "$ZERROR: ",$ZERROR,!
      WRITE "$ECODE: ",$ECODE
      RETURN
  }
  TRY {
    WRITE !,"2nd TRY block",!
    WRITE "This is where the code falls through",!
    WRITE "$ZERROR: ",$ZERROR,!
    WRITE "$ECODE: ",$ECODE
  }
  CATCH exp2 {
    WRITE !,"This is the 2nd CATCH exception handler",!
  }

関連項目

FeedbackOpens in a new tab