コマンド行ルーチンのデバッグ
ここでは、ObjectScript コードのテストとデバッグに使用する手法について説明します。InterSystems IRIS® データ・プラットフォームには、コードをデバッグする 2 つの方法があります。
-
ルーチン・コードで BREAK コマンドを使用して実行を中断し、実行内容を検証します。
-
ZBREAK コマンドで ObjectScript デバッガを呼び出して実行を中断し、コードと変数の両方を検証できます。
InterSystems IRIS には、ここで説明するように、ルーチンを中断し、完全なデバッグ機能をサポートするシェルに入る機能が含まれています。InterSystems IRIS には保護されたデバッグ・シェルも含まれています。これには、割り当てられた特権の超越や迂回をユーザができないという利点があります。
保護されたデバッグ・シェル
保護されたデバッグ・シェルは、機密データへのアクセスの制御に関して優れています。ユーザは、環境によって、変数のステッピングや表示などの基本的なデバッグを実行できますが、ルーチンの実行パスや結果を変更するいかなる操作も許可されません。これによって、操作、悪意のあるロール・エスカレーション、より高い権限で実行するコードの挿入などの問題を引き起こす可能性のあるアクセスを防止できます。
既定では、デバッグ・プロンプトのユーザは、現在のレベルの特権を保持します。デバッグ・プロンプトの保護されたシェルを有効にし、このことによってユーザが発行できるコマンドを制限するには、そのユーザに対して保護されたデバッグ・シェルを有効にする必要があります。
現在のユーザに対して有効にした場合、保護されたデバッグ・シェルは、BREAK コマンドが実行された時点、ブレークポイントまたはウォッチポイントが検出された時点、または捕えられていないエラーが発生した時点で開始されます。
保護されたデバッグ・シェル内では、ユーザは以下のものを実行できません。
-
変数を変更する可能性があるコマンド。
-
変数を変更する可能性がある関数。
-
他のルーチンを呼び出す可能性があるコマンド。
-
ルーチンのフローまたは環境に影響を及ぼすコマンド。
保護されたデバッグ・シェル内で、制限されたコマンドまたは関数をユーザが実行しようとすると、InterSystems IRIS はそれぞれ <COMMAND> エラーまたは <FUNCTION> エラーをスローします。
制限されるコマンドと関数
この節では、保護されたデバッグ・シェル内で制限されるアクティビティのリストを示します。
制限される ObjectScript コマンド
保護されたデバッグ・シェルで制限される ObjectScript コマンドは以下のとおりです。
-
CLOSE
-
DO
-
FOR
-
引数付きの GOTO
-
KILL
-
LOCK
-
MERGE
-
OPEN
-
QUIT
-
READ
-
RETURN
-
SET
-
TCOMMIT
-
TROLLBACK
-
TSTART
-
VIEW
-
XECUTE
-
ZINSERT
-
ZKILL
-
ZREMOVE
-
ZSAVE
-
ZW と ZZDUMP 以外のユーザ・コマンド
制限される ObjectScript 関数
保護されたデバッグ・シェルで制限される ObjectScript 関数は以下のとおりです。
-
$CLASSMETHOD
-
$COMPILE
-
$DATA(,var) — 引数が 2 つのもののみ
-
$INCREMENT
-
$METHOD
-
$ORDER(,,var) — 引数が 3 つのもののみ
-
$PROPERTY
-
$QUERY(,,var) — 引数が 3 つのもののみ
-
$XECUTE
-
$ZF
-
$ZSEEK
-
任意の外部関数
制限されるオブジェクト構成
いかなるメソッドまたはプロパティの参照も許可されません。プロパティ参照は、propertyGet メソッドを起動する可能性があるため制限されます。制限されるオブジェクト・メソッドおよびプロパティ構文の構成の例の一部を以下に示します。
-
#class(classname).ClassMethod()
-
oref.Method()
-
oref.Property
-
$SYSTEM.Class.Method()
-
..Method()
-
..Property
参照によって変数の受け渡しを行わない場合でも、メソッドによってパブリック変数が変更される可能性があります。プロパティ参照は propGet メソッドを起動する可能性があるため、いかなるプロパティ・アクセスも許可されません。
ObjectScript デバッガによるデバッグ
ObjectScript デバッガを使用すると、ルーチンのコードにデバッグ・コマンドを直接挿入し、ルーチンをテストできます。その後、コードの実行時にコマンドを発行し、アプリケーションの実行状況と処理フローをテストできます。以下は主な機能です。
-
ZBREAK コマンドを使用してコードにブレークポイントを設定し、その場所に達したときに特定の動作を実行します。
-
ローカル変数にウォッチポイントを設定し、その変数の値が変更されたときに特定の動作を実行します。
-
ブレークポイントとウォッチポイントの実行中は、別々のウィンドウで InterSystems IRIS とやり取りします。
-
実行パスが変更されたときは常に実行をトレースし、その記録を (ターミナルあるいは別のデバイスに) 出力します。
-
実行スタックを表示します。
-
デバイスでアプリケーションを実行中、デバッグの入出力はセカンド・デバイスで行われます。これにより、InterSystems IRIS アプリケーションを全画面で実行しながら、アプリケーションのターミナル入出力を中断せずにデバッグできます。
ブレークポイントとウォッチポイントの使用法
ObjectScript デバッガには、プログラムの実行を中断する 2 つの方法があります。
-
ブレークポイント
-
ウォッチポイント
ブレークポイントは、ZBREAK コマンドで指定する InterSystems IRIS ルーチン内の位置です。実行中のルーチンが指定行に達すると、InterSystems IRIS はルーチンの実行を中断します。オプションとして、定義したデバッグを実行する場合もあります。最大 20 個のルーチンまでブレークポイントを設定できます。また、1 つのルーチン内に最大 20 個までのブレークポイントを設定できます。
ウォッチポイントは、ZBREAK コマンドで識別する変数です。SET コマンドあるいは KILL コマンドで値を変更すると、ルーチンの実行またはZBREAK コマンド内で定義したデバッグの実行、あるいはその両方を中断できます。システム変数にウォッチポイントを指定することはできません。
定義したブレークポイントとウォッチポイントは、1 つのセッション内でのみ維持されます。したがって、ブレークポイントとウォッチポイントの定義を 1 つのルーチンあるいは XECUTE コマンド文字列に格納すると、セッション間でそれらを簡単に元に戻せるため便利です。
ブレークポイントとウォッチポイントの設定
ZBREAK コマンドを使用して、ブレークポイントとウォッチポイントを設定します。
構文
ZBREAK location[:action:condition:execute_code]
以下を示します。
引数 | 説明 |
---|---|
location | 必須項目。(ブレークポイントを設定する) コード位置、(ウォッチポイントを設定する) ローカル変数あるいはシステム変数を指定します。指定した位置にブレークポイント/ウォッチポイントが既に定義されている場合、新規の設定により古い設定が置き換えられます。システム変数にウォッチポイントを指定することはできません。 |
action | オプション — ブレークポイント/ウォッチポイントがトリガされた (引き起こされた) ときの動作を指定します。ブレークポイントの場合、動作はコード行が実行される前に発生します。またウォッチポイントの場合、動作はローカル変数を変更するコマンドの実行後に発生します。動作は、大文字あるいは小文字で指定できますが、引用符で囲む必要があります。 |
condition |
オプション — 中括弧または引用符で囲んだブーリアン式。ブレークポイントまたはウォッチポイントのトリガ時に評価されます。
condition が未指定の場合、既定では True です。 |
execute_code | オプション — condition が True の場合に実行される ObjectScript コードを指定します。コードがリテラルである場合、中括弧または引用符でそのコードを囲む必要があります。このコードは、動作が実行される前に実行されます。特殊なシステム変数 $TEST の値は、コードを実行する前に保存されます。コードの実行後、デバッグされたプログラムに存在する $TEST の値は復元されます。 |
疑問符 (?) を付けて ZBREAK を使用すると、ヘルプが表示されます。
コード位置でのブレークポイントの設定
$TEXT 関数への呼び出しで使用するルーチン行参照として、コード位置を指定します。実行がコードの指定した位置に到達した場合は常に、コード行が実行される前にブレークポイントが発生します。ルーチン名を指定しない場合、InterSystems IRIS は、現在のルーチンを参照しているものと見なします。
ブレークポイント実行コード内の引数なしの GOTO
引数なしの GOTO は、ブレークポイントの実行コードで使用できます。これは、デバッガの Break プロンプトで引数なしの GOTO を実行するのと同じ効果があるため、次のブレークポイントまで引き続き実行されます。
例えば、テスト中のルーチンが現在のネームスペースにある場合、位置の値は以下のようになります。
値 | ブレーク位置 |
---|---|
label^rou | ルーチン rou にある行ラベル label の行の前で中断 |
label+3^rou | ルーチン rou にある行ラベル label から 3行目の前で中断 |
+3^rou | ルーチン rou の 3 行目で中断 |
テスト中のルーチンが現在メモリにロードされている場合 (つまり、暗黙あるいは明示的に ZLOAD が実行された場合)、以下のような位置の値を使用できます。
値 | ブレーク位置 |
---|---|
label | label の行ラベルの前で中断 |
label+3 | label から 3 行目の前で中断 |
+3 | 3 行目の前で中断 |
ローカル変数名とシステム変数名でのウォッチポイントの設定
以下の状況で、ローカル変数名を使用してウォッチポイントを発生させることができます。
-
ローカル変数を生成したとき
-
SET コマンドがローカル変数値を変更したとき
-
KILL コマンドがローカル変数を削除したとき
変数名は、*a のようにアスタリスクが前に付きます。
配列変数名を指定すると、ObjectScript デバッガはすべての下位ノードを監視します。例えば、配列 a にウォッチポイントを設定し、これを a(5) あるいは a(5,1) に変更すると、ウォッチポイントがトリガされます。
ウォッチポイントの設定時、既存の変数は必要ありません。
以下の特殊なシステム変数も使用できます。
システム変数 | トリガ・イベント |
---|---|
$ZERROR | エラー発生時は常に、エラー・トラップの呼び出し前にトリガされます。 |
$ZTRAP | エラー・トラップが設定、あるいはクリアされる際は常にトリガされます。 |
$IO | 明示的に SET コマンドを実行するとトリガされます。 |
Action 引数の値
以下のテーブルは、ZBREAK の action 引数に使用できる値の説明です。
引数 | 説明 |
---|---|
"B" | 既定値です。"T" 動作を含む場合を除き、ZBREAK *a:"TB" のように明示的に "B" 動作を組み込み、ブレークを起こす必要があります。実行を中断し、行の位置を示すキャレット (^) と共に、ブレークが起こった行を表示します。その後、ターミナル・プロンプトが表示され、やり取りが可能となります。引数なしの GOTO コマンドで実行を再開します。 |
"L" | GOTO コマンドがシングル・ステップの実行を開始し、各行の最初で停止する以外は、"B" と同じです。DO コマンド、ユーザ定義関数、XECUTE コマンドに遭遇した場合、シングル・ステップ・モードは、そのコマンドあるいは関数が完了するまで一時中断します。 |
"L+" | GOTO コマンドがシングル・ステップの実行を開始し、各行の最初で停止する以外は、"B" と同じです。DO コマンド、ユーザ定義関数、XECUTE コマンドは、シングル・ステップ・モードを中断しません。 |
"S" | GOTO コマンドがシングル・ステップの実行を開始し、各コマンドの最初で停止する以外は、"B" と同じです。DO コマンド、ユーザ定義関数、FOR コマンド、XECUTE コマンドに遭遇した場合、シングル・ステップ・モードは、そのコマンドあるいは関数が完了するまで一時中断します。 |
"S+" | GOTO コマンドがシングル・ステップの実行を開始し、各コマンドの最初で停止する以外は、"B" と同じです。DO コマンド、ユーザ定義関数、FOR コマンド、XECUTE コマンドは、シングル・ステップ・モードを中断しません。 |
"T" | 他の引数と共に使用できます。トレース・デバイスにトレース・メッセージを出力します。この引数は、後述の ZBREAK /TRACE:ON コマンドでトレースを ON に設定した後にのみ機能します。トレース・デバイスは、ZBREAK /TRACE コマンドで定義しない限り、主デバイスになります。この引数をブレークポイントで使用すると、TRACE: ZBREAK at label2^rou2 というメッセージが表示されます。この引数をウォッチポイントで使用すると、監視中の変数名と実行中のコマンド名を指定するトレース・メッセージが表示されます。例えば次のコードの場合、変数 a は監視され、ルーチン test の行 test+1 で変更されました。TRACE: ZBREAK SET a=2 at test+1^test。"T" 動作を組み込む場合、ZBREAK *a:"TB" に "B" 動作も明示的に組み込む必要があります。これにより、実際のブレークが発生します。 |
"N" | このブレークポイント/ウォッチポイントでは、何も動作しません。condition 式は常に評価され、execute_code が実行されているかどうかを判定します。 |
ZBREAK の例
以下の例では、ローカル変数 a が削除されると常に実行を中断するウォッチポイントを設定します。動作は何も指定されていないため、"B" が指定されているものとします。
ZBREAK *a::"'$DATA(a)"
以下の例は、(ルーチン内から発行されるコマンドではなく) ダイレクト・モードの ObjectScript コマンドに対して動作する、上記のウォッチポイントを示しています。キャレット (^) は、実行を中断させるコマンドを示します。
USER>KILL a
KILL a
^
<BREAK>
USER 1s0>
以下の例は、実行を中断し、label2^rou 行の先頭にシングル・ステップ・モードを設定するブレークポイントです。
ZBREAK label2^rou:"L"
以下の例は、ルーチン実行時にどのようにブレークが実行されるかを示しています。キャレット (^) は、実行が中断した位置を示します。
USER>DO ^rou
label2 SET x=1
^
<BREAK>label2^rou
USER 2d0>
以下の例では、"N" 動作のため、行 label3^rou のブレークポイントは実行を中断しません。しかし、行 label3^rou に達した際に x<1 の場合、flag を x に設定します。
ZBREAK label3^rou:"N":"x<1":"SET flag=x"
以下の例は、a の値が変更されるたびに、^GLO のコードを実行するウォッチポイントを設定します。二重コロンは、condition 引数がないことを示しています。
ZBREAK *a:"N"::"XECUTE ^GLO"
以下の例は、b の値が変更されるたびに、トレース・メッセージを表示するウォッチポイントを設定します。トレース・メッセージは、トレース・モードが ZBREAK /TRACE:ON コマンドで ON になっている場合にのみ表示されます。
ZBREAK *b:"T"
以下の例は、変数 a が 5 に設定されると、シングル・ステップ・モードで実行を中断するウォッチポイントを設定します。
ZBREAK *a:"S":"a=5"
以下の例は、ブレークの発生時、キャレット記号 (^) は、変数 a を 5 に設定するコマンドを指定します。
USER>DO ^test
FOR i=1:1:6 SET a=a+1
^
<BREAK>
test+3^test
USER 3f0>WRITE a
5
ブレークポイントとウォッチポイントを無効にする
以下のいずれかを無効にできます。
-
特定のブレークポイントとウォッチポイント
-
すべてのブレークポイントあるいはウォッチポイント
特定のブレークポイントとウォッチポイントを無効にする
マイナス記号をブレークポイントあるいはウォッチポイントの位置指定の前に置くと、ブレークポイントあるいはウォッチポイントを無効にできます。以下のコマンドは、位置 label2^rou で事前に指定されたブレークポイントを無効にします。
ZBREAK -label2^rou
無効になったブレークポイントは “消失” しますが、その定義は維持されます。したがって、プラス記号をその前に置くと、無効にされたブレークポイントを有効にできます。以下のコマンドは、以前無効にされたブレークポイントを有効にします。
ZBREAK +label2^rou
すべてのブレークポイントとウォッチポイントを無効にする
位置を指定せずにプラス記号あるいはマイナス記号を使用して、すべてのブレークポイントまたはウォッチポイントを無効できます。
記号 | 説明 |
---|---|
ZBREAK - | 定義済みのすべてのブレークポイントとウォッチポイントを無効にします。 |
ZBREAK + | 定義済みのすべてのブレークポイントとウォッチポイントを有効にします。 |
ブレークポイントとウォッチポイントの実行を遅らせる
指定した数の反復の間、ブレークポイント/ウォッチポイントの実行を遅らせることもできます。実行する度ではなく定期的にブレークさせるように、ループ内にコード行を記述している場合もあります。このためには、通常どおりにブレークポイントを設定した後、位置の引数に続くカウントを無効にします。
以下の ZBREAK コマンドは、100 回反復される間、label2^rou のブレークポイントを無効にします。101 回目にこの行が実行されると、指定したブレークポイントの動作が発生します。
ZBREAK label2^rou ; establish the breakpoint
ZBREAK -label2^rou#100 ; disable it for 100 iterations
行が繰り返し実行されても、この行には FOR コマンドが含まれるため、遅らせたブレークポイントはデクリメントされません。
ブレークポイントとウォッチポイントの削除
次のように、ブレークポイント/ウォッチポイントの位置の前にマイナス記号を 2 つ付けて、ブレークポイントまたはウォッチポイントを個別に削除できます。
ZBREAK --label2^rou
ブレークポイント/ウォッチポイントを削除した後は、それを再度定義することにより削除したポイントをリセットできます。
すべてのブレークポイントを削除するには、以下のコマンドを発行します。
ZBREAK /CLEAR
このコマンドは、InterSystems IRIS プロセスが停止すると、自動的に実行されます。
シングル・ステップ・ブレークポイントの動作
シングル・ステップ実行を使用して、コードの各行あるいは各コマンドの最初で実行を停止できます。シングル・ステップ・ブレークポイントを設定し、各ステップで実行される動作と実行コードを指定できます。以下の構文を使用して、シングル・ステップ・ブレークポイントを定義します。
ZBREAK $:action[:condition:execute_code]
他のブレークポイントと異なり、ZBREAK $ はブレークを引き起こしません。ブレークは、シングル・ステップとして自動的に発生するからです。ZBREAK $ を使用すると、ルーチンのステップ実行時にデバッガがブレークする各ポイントで、動作を指定しコードを実行できます。これは、行あるいはコマンドの実行をトレースするのに特に役立ちます。例えば以下のコードは、アプリケーション ^TEST で実行された行をトレースします。
USER>ZBREAK /TRACE:ON
USER>BREAK "L+"
USER>ZBREAK $:"T"
"T" 単体で (つまり、その他のアクション・コードなしで) 指定すると、通常自動的に発生するシングル・ステップ・ブレークが抑制されます (また、他のアクション・コードを使用するかどうかにかかわらず、"N" アクション・コードを指定すれば、シングル・ステップ・ブレークが抑制されます)。
トレースとブレークの両方を発生させるには、以下の方法でシングル・ステップ・ブレークポイントの定義を設定します。
USER>ZBREAK $:"TB"
実行のトレース
以下の ZBREAK 形式を使用して、ZBREAK コマンドの "T" 動作を有効にするかどうかを制御できます。
ZBREAK /TRACE:state[:device]
state には、以下を指定できます。
状態 | 説明 |
---|---|
ON | トレース可能 |
OFF | トレース不可能 |
ALL | 次のコードと同等なコードを実行する場合、アプリケーションのトレース可能: ZBREAK /TRACE:ON[:device] BREAK "L+" ZBREAK $:"T" |
device で ALL あるいは ON 状態キーワードを使用する場合、トレース・メッセージは、主デバイスではなく、指定されたデバイスに転送されます。デバイスを開いていない場合、InterSystems IRIS は、WRITE オプションと APPEND オプションが付いたシーケンシャル・ファイルとしてそのデバイスを開こうとします。
OFF 状態キーワードを使用してデバイスを指定すると、現在ファイルが開いている場合に InterSystems IRIS はそのファイルを閉じます。
ZBREAK /TRACE:OFF により、ZBREAK /TRACE:ALL で設定したシングル・ステップ・ブレークポイントの定義が削除、または無効にされることはありません。また、ZBREAK /TRACE:ALL で設定した L+ シングル・ステップが消去されることもありません。また、ZBREAK --$ と BREAK "C" コマンドを発行し、シングル・ステップを削除する必要があります。あるいはその代わりに、BREAK "OFF" シングル・コマンドを使用して、プロセスのデバッグをすべて無効にできます。
トレース・メッセージは、T 動作に対応するブレークポイントで生成されます。例外として、トレース・メッセージの形式は、すべてのブレークポイントで以下のようになります。
Trace: line_reference での ZBREAK
line_reference は、参照するブレークポイントの行です。
コマンドでステップを実行する場合、トレース・メッセージの形式は、シングル・ステップのブレークポイントと若干異なります。
Trace: line_reference source_offset での ZBREAK
line_reference は参照するブレークポイントの行で、source_offset は、ブレークが発生したソース行位置への 0 ベースのオフセットです。
オペレーティング・システムの注釈
-
Windows — 別のデバイスへのトレース・メッセージは、COM1: など COM ポートに接続されているターミナル・デバイスに対して、Windows プラットフォームでサポートされています。コンソールあるいはターミナル・ウィンドウは使用できません。トレース・デバイスへのシーケンシャル・ファイルを指定できます。
-
UNIX® — 以下の方法で、UNIX® プラットフォームで別のデバイスにトレース・メッセージを送信します。
-
/dev/tty01 にログインします。
-
次の tty コマンドを入力し、デバイス名を検証します。
$ tty /dev/tty01
-
以下のコマンドを発行し、デバイス競合を避けます。
$ exec sleep 50000
-
作業ウィンドウに戻ります。
-
InterSystems IRIS を開始します。
-
以下のトレース・コマンドを発行します。
ZBREAK /T:ON:"/dev/tty01"
-
プログラムを実行します。
T 動作を実行するブレークポイントあるいはウォッチポイントを設定すると、 /dev/tty01 に接続されたウィンドウに、トレース・メッセージが表示されます。
-
トレース・メッセージ形式
ブレークポイントをコードに設定すると、以下のメッセージが表示されます。
Trace: ZBREAK at label2^rou2
ウォッチポイント変数を設定すると、以下のメッセージが表示されます。
Trace: ZBREAK SET var=val at label2^rou2
Trace: ZBREAK SET var=Array Val at label2^rou2
Trace: ZBREAK KILL var at label2^rou2
-
var は、監視される変数です。
-
val は、その変数に設定された新しい値です。
NEW コマンドを発行すると、トレース・メッセージは受け取りません。しかし、NEW レベルの変数で次に SET あるいは KILL を発行すると、変数のトレースが実行されます。変数がルーチンに参照渡しされると、その名前が変更された場合も、変数は引き続き追跡されます。
割り込みキーと Break コマンド
通常、割り込みキー (一般的に CTRL-C) を続けて押すと、トラップ可能な (<INTERRUPT>) エラーが生成されます。<INTERRUPT> エラーではなく、ブレークを発生させる割り込み処理を設定するには、ZBREAK コマンド ZBREAK /INTERRUPT:Break を使用します。
これにより、デバイスのアプリケーション・レベルで割り込みが無効の場合も、割り込みキーを押したときにブレークが発生します。
ターミナルから読み取り中に割り込みキーを押すと、ブレーク・モード・プロンプトを表示するため、Enter キーを押す必要があります。ブレークではなくエラーを生成するよう割り込み処理をリセットするには、コマンド ZBREAK /INTERRUPT:NORMAL を発行します。
現在のデバッグ環境情報の表示
定義されたすべてのブレークポイントあるいはウォッチポイントを含め、現在のデバッグ環境の情報を表示するには、引数なしの ZBREAK コマンドを発行します。
引数なしの ZBREAK コマンドは、以下のデバッグ環境の状態を示します。
-
CTRL-C がブレークを生じさせるかどうか
-
"T" 動作で指定されたトレースの出力が、ZBREAK コマンドで表示されるかどうか
-
有効/無効状態、動作、条件、実行可能コードを指定するフラグを持つ、すべての定義済みブレークポイントの位置
-
有効/無効状態、動作、条件、実行可能コードを指定するフラグを持つウォッチポイントのすべての変数
このコマンドからの出力は、デバッグ・デバイスとして定義されたデバイスに表示されます。ZBREAK /DEBUG コマンドで異なるデバッグ・デバイスを定義しない限り、ユーザの主デバイスに出力されます。デバイスの定義は、"デバッグ・デバイスの使用法" のセクションで説明しています。
以下のテーブルは、各ブレークポイントとウォッチポイントに提供されるフラグの説明です。
表示セクション | 意味 |
---|---|
ブレークポイント/ウォッチポイントの識別 | ブレークポイントのルーチンの行ウォッチポイントのローカルの変数 |
F: | ZBREAK コマンドで定義された動作タイプの情報を提供するフラグです。 |
S: | ZBREAK - コマンドで定義されたブレークポイント/ウォッチポイントの実行を遅らせる回数です。 |
C: | ZBREAK コマンドで設定された Condition 引数です。 |
E: | ZBREAK コマンドで設定された Execute_code 引数です。 |
以下のテーブルは、ブレークポイント/ウォッチポイントの表示で F: 値をどのように解釈するかを示しています。F: 値は、最初の列にある適切な値のリストです。
値 | 意味 |
---|---|
E | 有効なブレークポイント/ウォッチポイント |
D | 無効なブレークポイント/ウォッチポイント |
B | ブレークの実行 |
L | "L" の実行 |
L+ | "L+" の実行 |
S | "S" の実行 |
S+ | "S+" の実行 |
T | トレース・メッセージの出力 |
既定表示
最初に InterSystems IRIS を開いて ZB を使用するとき、出力は以下のようになります。
USER>ZBREAK
BREAK:
No breakpoints
No watchpoints
これは、以下を示します。
-
トレースの実行は OFF です。
-
CTRL-C が押されると、ブレークは無効になります。
-
ブレークポイント/ウォッチポイントは未定義です。
既存のブレークポイントとウォッチポイントの表示
この例では、2 つのブレークポイントと 1 つのウォッチポイントの定義を示しています。
USER>ZBREAK +3^test:::{WRITE "IN test"}
USER>ZBREAK -+3^test#5
USER>ZBREAK +5^test:"L"
USER>ZBREAK -+5^test
USER>ZBREAK *a:"T":"a=5"
USER>ZBREAK /TRACE:ON
USER>ZBREAK
BREAK: TRACE ON
+3^test F:EB S:5 C: E:"WRITE ""IN test"""
+5^test F:DL S:0 C: E:
a F:ET S:0 C:"a=5" E:
最初の 2 つの ZBREAK コマンドは、ブレークポイントの遅延を定義しています。その次の 2 つの ZBREAK は無効なブレークポイントを、5 番目の ZBREAK はウォッチポイントを定義しています。6 番目の ZBREAK コマンドはトレースの実行を有効にし、引数のない最後の ZBREAK コマンドは、現在のデバッグ設定情報を表示します。
例えば、ZBREAK は以下を表示します。
-
トレースは ON です。
-
CTRL-C が押されると、ブレークは無効になります。
その後出力は、2 つのブレークポイントと 1 つのウォッチポイントを示します。
-
最初のブレークポイントの F フラグは EB、S フラグは 5 です。つまり、ブレークポイントは、行の 5 回目の実行で発生します。E フラグは、ブレーク用のターミナル・プロンプトが表示される前に実行される実行可能コードを表示します。
-
2 番目のブレークポイントの F フラグは DL です。これは、ブレークポイントの無効を意味しますが、有効の場合ブレークが発生し、ブレークポイント位置の後ろの各コード行をシングル・ステップで実行します。
-
ウォッチポイントの F フラグは ET です。これは、ウォッチポイントが有効であることを意味します。トレース実行が ON の場合、トレース・メッセージがトレース・デバイスに表示されます。トレース・デバイスを定義していない場合、トレース・デバイスは主デバイスになります。
-
C フラグは、condition が True の場合にのみトレースが表示されることを意味します。
デバッグ・デバイスの使用法
デバッグ・デバイスは、以下のようなデバイスです。
-
ZBREAK コマンドは、デバッグ環境情報を表示します。
-
ターミナル・プロンプトは、ブレーク発生時に表示されます。
Windows プラットフォームでは、別のデバイスへのトレース・メッセージは、COM1: など COM ポートに接続されているターミナル・デバイスでのみサポートされています。
InterSystems IRIS を実行すると、デバッグ・デバイスが主デバイスとして自動的に設定されます。いつでも、デバッグ入出力は、コマンド ZBREAK /DEBUG:"device" で代わりのデバイスに送信できます。
また、オペレーティング・システム固有の動作も実行可能です。
UNIX® システムで tty01 デバイスをブレーク状態にするには、以下のコマンドを発行します。
ZBREAK /D:"/dev/tty01/"
CTRL-C あるいはブレークポイント、ウォッチポイントがトリガされてブレークが発生すると、デバイスに接続されたウィンドウに表示されます。そのウィンドウが、アクティブ・ウィンドウになります。
デバイスが開いていない場合、自動的に OPEN コマンドが実行されます。デバイスが指定した位置で既に開いている場合、あらゆる既存の OPEN パラメータが優先されます。
指定したデバイスがインタラクティブでない (例えばターミナル) 場合、ブレークから戻ることができません。しかし、システムでこの制約が強制されているわけではありません。
ObjectScript デバッガの例
最初に、以下に示す test という簡単なプログラムをデバッグします。目標は、変数 a に 1 を、変数 b に 2 を、変数 c に 3 を格納することです。
test; Assign the values 1, 2, and 3 to the variables a, b, and c
SET a=1
SET b=2
SET c=3 KILL a WRITE "in test, at end"
QUIT
しかし、test を実行すると、b と c のみが正しい値を取得します。
USER>DO ^test
in test, at end
USER>WRITE
b=2
c=3
USER>
明らかにこのプログラムの問題は、変数 a が行 4 で KILL コマンドによって削除されることですが、この問題を特定するためにデバッガを使用する必要があると想定します。
ZBREAK コマンドを使用して、ルーチン test の各コード行 ("L" 動作) をシングル・ステップに設定できます。ステップを実行して a の値を書き込むことにより、4 行目に問題があることを判定します。
USER>NEW
USER 1S1>ZBREAK
BREAK
No breakpoints
No watchpoints
USER 1S1>ZBREAK ^test:"L"
USER 1S1>DO ^test
SET a=1
^
<BREAK>test+1^test
USER 3d3>WRITE a
<UNDEFINED>^test
USER 3d3>GOTO
SET b=2
^
<BREAK>test+2^test
USER 3d3>WRITE a
1
USER 3d3>GOTO
SET c=3 KILL a WRITE "in test, at end"
^
<BREAK>test+3^test
USER 3d3>WRITE a
1
USER 3d3>GOTO
in test, at end
QUIT
^
<BREAK>test+4^test
USER 3d3>WRITE a
WRITE a
^
<UNDEFINED>^test
USER 3d3>GOTO
USER 1S1>
これでこの行を検証し、KILL a コマンドを発見できます。さらに複雑なコードでは、その行から ("S" 動作) コマンドでシングル・ステップを実行したい場合もあります。
問題が、DO、FOR、XECUTE コマンド、ユーザ定義関数で発生した場合、"L+" あるいは "S+" 動作を使用して、コードの下位レベルにある行あるいはコマンドからシングル・ステップを実行します。
ObjectScript デバッガ・エラーの理解
ObjectScript デバッガは、適切な InterSystems IRIS エラー・メッセージを持つ条件引数あるいは実行引数でエラーが発生すると、フラグを立てます。
エラーが execute_code 引数内に存在する場合、実行コードがエラー・メッセージの前に表示されると、実行コードは条件コードに囲まれます。条件特殊変数 ($TEST) は、常に実行コードの最後で 1 に設定されるため、残りのデバッガ処理コードは適切に動作します。制御がルーチンに戻ると、ルーチン内の $TEST 値はリストアされます。
サンプル・プログラム test に対し、以下の ZBREAK コマンドを発行するとします。
USER>ZBREAK test+1^test:"B":"a=5":"WRITE b"
このプログラム test で変数 b は、行 test+1 で定義されていないため、エラーが発生します。以下のようなエラーが表示されます。
IF a=5 XECUTE "WRITE b" IF 1
^
<UNDEFINED>test+1^test
condition を定義しなかった場合、人工的に True の条件を実行コードの前後に定義できます。以下はその例です。
USER>IF 1 WRITE b IF 1
BREAK コマンドによるデバッグ
InterSystems IRIS の BREAK コマンドには、3 つの形式があります。
-
ルーチン・コードに挿入された引数なしの BREAK により、その場所においてブレークポイントが設定されます。コード実行中にこのブレークポイントと遭遇すると、実行が中断されて、ターミナル・プロンプトに戻ります。
-
文字列引数付きの BREAK では、行ごとまたはコマンドごとでのコードのステップ実行を可能にするブレークポイントを設定/削除します。
-
整数の引数付きの BREAK コマンドでは、CTRL-C によるユーザ割り込みを有効/無効化します。(詳細は "BREAK" コマンドを参照してください。)
ルーチンの実行を中断する引数なし BREAK の使用法
実行中のルーチンを中断し、プロセスをターミナル・プロンプトに戻すには、ルーチンで実行を一時的に中断させたい位置に、引数なしの BREAK を入力します。
InterSystems IRIS が BREAK に遭遇すると、以下のステップが実行されます。
-
実行中のルーチンを中断します。
-
プロセスをターミナル・プロンプトに戻します。主デバイスの入出力リダイレクトを使用するアプリケーションをデバッグすると、リダイレクトはデバッグ・プロンプトでオフになり、デバッグ・コマンドからの出力がターミナルに表示されます。
これにより、ObjectScript コマンドを発行し、データを修正できます。また、エラーまたは追加の BREAK があっても、他のルーチンやサブルーチンを実行できます。デバッグ・ターミナル・プロンプトから ObjectScript コマンドを発行すると、このコマンドは直ちに実行されます。実行中のルーチンには挿入されません。このコマンド実行は、通常のターミナル・プロンプトの動作と同じです。1 つ違う点は、タブ文字によって続行されたコマンドがデバッグ・ターミナル・プロンプトから実行されることです。タブ文字によって続行されたコマンドは、通常のターミナル・プロンプトからは実行されません。
ルーチンが中断された位置で実行を再開するには、引数なしの GOTO コマンドを発行します。
コード内の引数なしの BREAK コマンドに後置条件を指定すると、ルーチンを変更しなくても、単に後置条件変数を設定するだけで同じコードを再実行できるので便利です。例えば、ルーチンに以下の行があるとします。
CHECK BREAK:$DATA(debug)
変数 debug を設定すると、ルーチンを中断し、ジョブをターミナル・プロンプトに戻すことができます。また、変数 debug をクリアすると、ルーチンの実行を継続できます。
詳細は、"コマンド後置条件式" を参照してください。
ルーチンの実行を中断する引数付き BREAK の使用法
中断したいルーチンのすべての位置に、引数なし BREAK コマンドを置く必要はありません。InterSystems IRIS では、コードのステップ実行を可能にする引数オプションがいくつか用意されています。コードのステップ実行は、シングル・ステップ (BREAK “S”) またはコマンド行 (BREAK “L”) を使用して行えます。これらの文字コード引数のすべてのリストについては、BREAK コマンドを参照してください。
BREAK “S” と BREAK “L” の一つの違いは、多数のコマンド行が複数ステップで構成されることにあります。このことは必ずしも明白になっているわけではありません。例えば、以下はすべて単一行 (および単一 ObjectScript コマンド) ですが、それぞれが 2 ステップで解析されます :SET x=1,y=2、KILL x,y、WRITE “hello”,!、IF x=1,y=2。
BREAK “S” と BREAK “L” は、ラベル行、コメント、および TRY 文を無視します (ただし、両方ともに TRY ブロックの閉じ中括弧でブレークします)。BREAK “S” は CATCH 文でブレークしますが (CATCH ブロックが入力された場合)、BREAK “L” はブレークしません。
BREAK でプロセスをターミナル・プロンプトに戻した場合、ブレークの状態はスタックされません。したがって、ブレークの状態を変更した場合、引数なしの GOTO を発行して実行中のルーチンに戻ったときに、その新規の状態が有効なままになります。
DO、XECUTE、FOR、またはユーザ定義関数が実行されるたびに、InterSystems IRIS はブレークの状態をスタックします。BREAK "C" を選択してブレークを OFF にすると、システムは DO、XECUTE、FOR、またはユーザ定義関数の最後にブレークの状態をリストアします。そうしない場合、InterSystems IRIS はスタックされた状態を無視します。
このように、下位のサブルーチン・レベルでブレークを有効にすると、ルーチンが上位のサブルーチン・レベルに戻った後、ブレークが継続されます。一方、上位レベルで有効だったブレークを下位サブルーチン・レベルで無効にした場合、上位レベルに戻ると、ブレークが再開されます。BREAK "C-" を使用して、すべてのレベルでブレークを無効にすることができます。
BREAK “L+” または BREAK “S+” を使用して、DO、XECUTE、FOR、またはユーザ定義関数内でブレークを有効にすることができます。
BREAK “L-” を使用すると、現在のレベルでのブレークが無効になりますが、前のレベルでの改行が有効になります。BREAK “S-” を使用すると、現在のレベルでのブレークが無効になりますが、前のレベルでのシングル・ステップ・ブレークが有効になります。
デバッグの停止
プロセスで作成されたすべてのデバッグを削除するには、BREAK "OFF" コマンドを使用します。このコマンドは、すべてのブレークポイントとウォッチポイントを削除し、すべてのプログラム・スタック・レベルでステップ実行を無効にします。また、デバッグとトレース・デバイスに関連するものも削除しますが、それらを閉じません。
BREAK "OFF" コマンドを実行することは、以下の一連のコマンドを発行することと同じです。
ZBREAK /CLEAR
ZBREAK /TRACE:OFF
ZBREAK /DEBUG:""
ZBREAK /ERRORTRAP:ON
BREAK "C-"
ターミナル・プロンプトのプログラム・スタック情報表示
BREAK コマンドがルーチンの実行を中断したとき、あるいはエラーが発生したとき、プログラム・スタックは、スタックされた情報の一部を維持します。このような状態になった場合、この情報の概要がターミナル・プロンプトの一部として表示されます (namespace>)。例えば、この情報は、USER 5d3> の形式で表示される場合があります。各要素は以下のとおりです。
文字 | 説明 |
---|---|
5 | 5 つのスタック・レベルがあることを示します。スタック・レベルは DO、FOR、XECUTE、NEW、ユーザ定義関数の呼び出し、エラー状態、またはブレーク状態が原因となる可能性があります。 |
d | 最後にスタックされた項目が DO であることを示します。 |
3 | 3 つの NEW 状態、パラメータ渡し、またはユーザ定義関数がスタックにあることを示します。NEW コマンド、パラメータ渡し、ユーザ定義関数がスタックされていない場合、この値は 0 です。 |
ターミナル・プロンプトの文字コードを以下のテーブルに示します。
プロンプト | 定義 |
---|---|
d | DO |
e | ユーザ定義関数 |
f | FOR ループ |
x | XECUTE |
B | BREAK 状態 |
E | エラー状態 |
N | NEW 状態 |
S | サインオン状態 |
以下の例では、スタック・フレーム追加時において、コマンド行の文が結果のターミナル・プロンプトを伴って表示されています。
USER>NEW
USER 1S1>NEW
USER 2N1>XECUTE "NEW WRITE 123 BREAK"
<BREAK>
USER 4x1>NEW
USER 5B1>BREAK
<BREAK>
USER 6N2>
QUIT 1 を使用して、プログラム・スタックを戻すことができます。以下は、スタックの巻き戻し時におけるターミナル・プロンプトの例です。
USER 6f0>QUIT 1 /* an error occurred in a FOR loop. */
USER 5x0>QUIT 1 /* the FOR loop was in code invoked by XECUTE. */
USER 4f0>QUIT 1 /* the XECUTE was in a FOR loop. */
USER 3f0>QUIT 1 /* that FOR loop was nested inside another FOR loop. */
USER 2d0>QUIT 1 /* the DO command was used to execute the program. */
USER 1S0>QUIT 1 /* sign on state. */
USER>
FOR ループおよび WHILE ループ
FOR または WHILE のいずれかを使用して、同じ操作を実行できます。つまり、イベント (通常はカウンタのインクリメント) によって実行がループを抜けるまでループすることができます。ただし、どちらのループ構造を使用するかにより、コード・モジュールに対するシングル・ステップ (BREAK "S+" または BREAK "L+") デバッグの実行に影響があります。
FOR ループでは、スタックに新しいレベルがプッシュされます。WHILE ループでは、スタック・レベルは変更されません。FOR ループをデバッグする場合、FOR ループ内からスタックをポップすると (BREAK "C" GOTO または QUIT 1 を使用)、FOR コマンド構文の終了直後から、このコマンドでのシングル・ステップ・デバッグを続行できます。WHILE ループをデバッグする場合は、BREAK "C" GOTO または QUIT 1 を使用して発行してもスタックはポップされません。したがって、WHILE コマンドの終了後にシングル・ステップ・デバッグは続行されません。残りのコードはブレークなしで実行されます。
BREAK あるいはエラー後の実行の再開
BREAK あるいはエラーの後にターミナル・プロンプトに戻ると、InterSystems IRIS は、BREAK あるいはエラーの原因となったコマンドの位置を記録します。その後、ターミナル・プロンプトで引数なしの GOTO を入力するだけで、次のコマンドで実行を再開できます。
USER 4f0>GOTO
引数付きの GOTO を入力すると、以下のように、ブレークあるいはエラーが発生する同じルーチン内の別の行頭から実行を再開できます。
USER 4f0>GOTO label3
また、異なるルーチンの行頭から実行を再開できます。
USER 4f0>GOTO label3^rou
または、引数なしの QUIT コマンドで、プログラム・スタックをクリアすることもできます。
USER 4f0>QUIT
USER>
サンプル・ダイアログ
以下はサンプルで使用されるルーチンです。
MAIN ; 03 Jan 2019 11:40 AM
SET x=1,y=6,z=8
DO ^SUB1 WRITE !,"sum=",sum
QUIT
SUB1 ; 03 Jan 2019 11:42 AM
SET sum=x+y+z
QUIT
BREAK "L" により、ルーチン SUB1 でブレークは発生しません。
USER>BREAK "L"
USER>DO ^MAIN
SET x=1,y=6,z=8
^
<BREAK>MAIN+1^MAIN
USER 2d0>GOTO
DO ^SUB1 WRITE !,"sum=",sum
^
<BREAK>MAIN+2^MAIN
USER 2d0>GOTO
sum=15
QUIT
^
<BREAK>MAIN+3^MAIN
USER 2d0>GOTO
USER>
BREAK"L+" により、ルーチン SUB1 でブレークも発生します。
USER>BREAK "L+"
USER>DO ^MAIN
SET x=1,y=6,z=8
^
<BREAK>MAIN+1^MAIN
USER 2d0>GOTO
DO ^SUB1 WRITE !,"sum=",sum
^
<BREAK>MAIN+2^MAIN
USER 2d0>GOTO
SET sum=x+y+z
^
<BREAK>SUB1+1^SUB1
USER 3d0>GOTO
QUIT
^
<BREAK>SUB1+2^SUB1
USER 3d0>GOTO
sum=15
QUIT
^
<BREAK>MAIN+3^MAIN
USER 2d0>GOTO
USER>
ターミナル・プロンプトで使用する NEW コマンド
引数なしの NEW コマンドは、事実上すべての記号をシンボル・テーブルに格納します。したがって、空のシンボル・テーブルを実行できます。エラーあるいは BREAK の発生後に、このコマンドが特に役立ちます。
シンボル・テーブルの妨げにならずに他のルーチンを実行するには、ターミナル・プロンプトで引数なしの NEW コマンドを発行します。その後、システムは以下を実行します。
-
プログラム・スタックに現在のフレームをスタックします。
-
新規スタック・フレームのターミナル・プロンプトを返します。
例えば以下のようになります。
USER 4d0>NEW
USER 5B1>DO ^%T
3:49 PM
USER 5B1>QUIT 1
USER 4d0>GOTO
5B1> プロンプトは、システムが BREAK から入った現在のフレームをスタックしたことを示します。1 は、NEW コマンドが変数情報をスタックしたことを示し、この変数情報は、QUIT 1 を発行することで削除できます。実行を再開する場合は、QUIT 1 を発行して古いシンボル・テーブルをリストアし、GOTO を発行して実行を再開します。
NEW コマンド、パラメータ渡し、ユーザ定義関数を使用するたびに、システムは情報をスタックに格納し、後で現在のサブルーチンまたは XECUTE レベルの明示的または暗黙的 QUIT により特定の編集を削除して他の値をリストアする必要があることを示します。
NEW コマンド、パラメータ渡し、ユーザ定義関数が実行されたかどうか (その結果一部の変数がスタックされます)、また実行された場合、既存情報をどのスタックまで戻すかどうかがわかると役立ちます。
ターミナル・プロンプトで使用する QUIT コマンド
ターミナル・プロンプトから引数なしの QUIT コマンドを入力すると、すべての項目をプログラム・スタックから削除できます。
USER 4f0>QUIT
USER>
プログラム・スタックからいくつかの項目のみを除外するには (例えば、現在実行中のサブルーチンから出て、前の DO レベルに戻る場合)、整数の引数で QUIT を使用します。例えば、QUIT 1 はプログラム・スタックの最後の項目を削除し、QUIT 3 は最後の 3 つの項目を削除します。以下はそのコード例です。
9f0>QUIT 3
6d0>
InterSystems IRIS エラー・メッセージ
InterSystems IRIS は、<ERROR> のように、<> 山括弧内にエラー・メッセージを表示します。その後には、エラー発生時にルーチンが実行していた行の参照が続きます。キャレット記号 (^) は、行参照とルーチンを区切ります。また、エラー発生時に実行するコマンドの最初の文字の下に、キャレット記号と共に中間コード行が表示されます。例えば以下のようになります。
SET x=y+3 DO ^ABC
^
<UNDEFINED>label+3^rou
このエラー・メッセージは、rou ルーチンの label+3 行で、<UNDEFINED> エラー (変数 y への参照) が発生したことを示しています。この時点で、このメッセージも特殊変数 $ZERROR の値となります。
スタックを表示する %STACK の使用法
%STACK ユーティリティを使用して、以下を実行できます。
%STACK の実行
以下のコマンドを入力して、%STACK を実行します。
USER>DO ^%STACK
この例で示されているように、%STACK ユーティリティは、変数を持たない現在のプロセス・スタックを表示します。
Level Type Line Source
1 SIGN ON
2 DO ~DO ^StackTest
3 NEW ALL/EXCL NEW (E)
4 DO TEST+1^StackTest SET A=1 ~DO TEST1 QUIT ;level=2
5 NEW NEW A
6 DO TEST1+1^StackTest ~DO TEST2 ;level = 3
7 ERROR TRAP SET $ZTRAP="TrapLabel^StackTest"
8 XECUTE TEST2+2^StackTest ~XECUTE "SET A=$$TEST3()"
9 $$EXTFUNC ^StackTest ~SET A=$$TEST3()
10 PARAMETER AA
11 DIRECT BREAK TEST3+1^StackTest ~BREAK
12 DO ^StackTest ~DO ^%STACK
現在の実行スタック表示の下で、%STACK により、スタックの表示動作を求める Stack Display Action プロンプトが表示されます。このプロンプトで疑問符 (?) を入力すると、ヘルプを表示できます。このプロンプトで Return キーを押すと、%STACK を終了できます。
プロセス実行スタックの表示
Stack Display Action で入力した内容によって、以下の 4 種類の形式で現在のプロセス実行スタックを表示できます。
-
*F を入力すると、変数なしのスタックを表示
-
*V を入力すると、特定のローカル変数付きスタックを表示
-
*P を入力すると、すべてのローカル変数付きスタックを表示
-
*A を入力すると、プロセス状態変数リストに先行するすべてのローカル変数付きスタックを表示
次に、%STACK により Display on Device プロンプトが表示されます。ここでは、この情報の表示先を指定できます。Return キーを押すと、この情報を現在のデバイスに表示できます。
変数なしスタックの表示
変数なしのプロセス実行スタックは、初めて %STACK ユーティリティを起動したとき、または Stack Display Action プロンプトで *F を入力したときに表示されます。
特定の変数付きスタックの表示
Stack Display Action プロンプトで、*V を入力します。これにより、このスタックで記録したいローカル変数の名前の入力を求められます。単一の変数、またはコンマで区切られた変数のリストを指定します。すべてのローカル変数の名前と値が返されます。以下の例では、変数 e が記録され、Return キーを押すと情報がターミナルに表示されます。
Stack Display Action: *V
Now loading variable information ... 2 done.
Variable(s): e
Display on
Device: <RETURN>
すべての定義済み変数付きスタックの表示
Stack Display Action プロンプトで *P を入力すると、すべての定義済みローカル変数の現在値と共に、プロセス実行スタックを表示できます。
状態変数を含むすべての変数付きスタックの表示
Stack Display Action プロンプトで *A を入力すると、すべての利用可能なレポートを表示できます。レポートは、以下の順序で発行されます。
-
プロセス状態内部変数
-
すべてのローカル変数の名前と値を伴ったプロセス実行スタック
スタックの表示の理解
スタックの各項目は、フレーム と呼ばれます。以下のテーブルは、各フレームに提供される情報を示します。
見出し | 説明 |
---|---|
レベル | スタック内のレベルを識別します。スタック内の一番古い項目が 1 番です。関連付けられたレベル番号のないフレームは、そのすぐ上に表示されるレベルと同じになります。 |
タイプ | スタックのフレーム・タイプを識別します。タイプは次のようになります。DIRECT BREAK : BREAK コマンドが発生し、ダイレクト・モードに戻りました。DIRECT CALLIN : InterSystems IRIS コールイン・インタフェースを使用して、InterSystems IRIS プロセスが InterSystems IRIS 外部のアプリケーションから開始されました。DIRECT ERROR : エラーが発生し、ダイレクト・モードに戻りました。DO : DO コマンドが実行されました。ERROR TRAP : ルーチンが $ZTRAP を設定した場合、このフレームは、エラーによって実行が継続する位置を識別します。FOR : FOR コマンドが実行されました。NEW : NEW コマンドが実行されました。NEW コマンドが引数付きの場合、引数は表示されます。SIGN ON : InterSystems IRIS プロセスの実行が開始されました。XECUTE : XECUTE コマンドが実行されました。$XECUTE 関数が実行されました。$$EXTFUNC : ユーザ定義関数が実行されました。 |
行 | 使用可能な場合、label+offset^routine の形式で、フレームに関連付けられた ObjectScript ソース行を識別します。 |
ソース | 使用可能な場合、ソース・コードを表示します。ソースが長すぎて表示領域に表示できない場合、水平スクロールを使用できます。デバイスが行表示対応の場合、ソースは折り返され、その後の行の先頭に ... が付きます。 |
以下のテーブルは、各フレーム・タイプごとにレベル、行、ソース値が使用できるかどうかを示します。レベルの下の "No" は、レベル番号がインクリメントされず、表示されないことを示します。
フレーム・タイプ | レベル | 行 | ソース |
---|---|---|---|
DIRECT BREAK | あり | あり | あり |
DIRECT CALL IN | あり | なし | なし |
DIRECT ERROR | あり | あり | あり |
DO | あり | あり * | あり |
ERROR TRAP | なし | なし | なし (しかし、新規 $ZTRAP 値は表示されます) |
FOR | なし | あり | あり |
NEW | なし | なし | NEW の形式 (包括的または排他的) と影響を受けた変数を示します。 |
PARAMETER | なし | なし | 仮パラメータ・リストを示します。パラメータが参照渡しされる場合は、同じメモリ位置を指すその他の変数を示します。 |
SIGN ON | あり | なし | いいえ |
XECUTE | あり | あり * | あり |
$$EXTFUNC | あり | あり * | あり |
* 行の値は、ターミナル・プロンプトから呼び出された場合、空白になります。 |
%STACK 表示からの移動
%STACK 表示が複数画面にわたる場合、画面の左下にプロンプト -- more -- が表示されます。最後のページには、プロンプト -- fini -- が表示されます。? を入力すると、%STACK 表示内での移動に使用するキー操作が表示されます。
- - - Filter Help - - -
<space> Display next page.
<return> Display one more line.
T Return to the beginning of the output.
B Back up one page (or many if arg>1).
R Redraw the current page.
/text Search for \qtext\q after the current page.
A View all the remaining text.
Q Quit.
? Display this screen
# specify an argument for B, L, or W actions.
L set the page length to the current argument.
W set the page width to the current argument.
-- more -- あるいは -- fini -- プロンプトが表示される場合は常に、上記に表示されたいずれかのコマンドを入力します。
B、L、W コマンドを入力する場合、コマンド文字の前に数値引数を入力します。例えば、2B と入力すると 2 ページ前に戻ります。また、20L を入力すると、20 行の長さにページが設定されます。
ページは、実際に表示される行数に合わせて設定してください。そうしない場合、ページを上下すると一部の行が表示されない可能性があります。既定のページの長さは 23 です。
特定のスタック・レベルでの変数の表示
指定されたスタック・フレーム・レベルに存在する変数を表示するには、Stack Display Action プロンプトで ?# と入力します。# には、スタック・フレーム・レベルを入力します。以下の例は、レベル 1 の変数を要求した場合の表示を示します。
Stack Display Action: ?1
The following Variables are defined for Stack Level: 1
E
Stack Display Action:
この情報を、%SYS.ProcessQueryOpens in a new tab VariableList クラス・クエリを使用して表示することもできます。
変数付きのスタック・レベルの表示
Stack Display Action プロンプトに ?? と入力すると、すべてのスタック・レベルで定義された変数を表示できます。?? と入力した場合に表示される例は、以下のとおりです。
Stack Display Action: ??
Now loading variable information ... 19
Base Stack Level: 5
A
Base Stack Level: 3
A B C D
Base Stack Level: 1
E
Stack Display Action:
プロセス状態変数の表示
$IO のようなプロセス状態変数を表示するには、"Stack Display Action" プロンプトに *S と入力します。次の表に示すように、これらの定義された変数 (プロセス状態内部) が表示されます。
プロセス状態内部 | ドキュメント |
---|---|
$D = | $DEVICE 特殊変数 |
$EC = ,M9, | $ECODE 特殊変数 |
$ES = 4 | $ESTACK 特殊変数 |
$ET = | |
$H = 64700,50668 | $HOROLOG 特殊変数 |
$I = |TRM|:|5008 | $IO 特殊変数 |
$J = 5008 | $JOB 特殊変数 |
$K = $c(13) | $KEY 特殊変数 |
$P = |TRM|:|5008 | $PRINCIPAL 特殊変数 |
$Roles = %All | $ROLES 特殊変数 |
$S = 268315992 | $STORAGE 特殊変数 |
$T = 0 | $TEST 特殊変数 |
$TL = 0 | $TLEVEL 特殊変数 |
$USERNAME = glenn | $USERNAME 特殊変数 |
$X = 0 | $X 特殊変数 |
$Y = 17 | $Y 特殊変数 |
$ZA = 0 | $ZA 特殊変数 |
$ZB = $c(13) | $ZB 特殊変数 |
$ZC = 0 | $ZCHILD 特殊変数 |
$ZE = <DIVIDE> | $ZERROR 特殊変数 |
$ZJ = 5 | $ZJOB 特殊変数 |
$ZM = RY\Latin1\K\UTF8\ | $ZMODE 特殊変数 |
$ZP = 0 | $ZPARENT 特殊変数 |
$ZR = ^||a | $ZREFERENCE 特殊変数 |
$ZS = 262144 | $ZSTORAGE 特殊変数 |
$ZT = | $ZTRAP 特殊変数 |
$ZTS = 64700,68668.58 | $ZTIMESTAMP 特殊変数 |
$ZU(5) = USER | $NAMESPACE |
$ZU(12) = c:\intersystems\iris\mgr\ | NormalizeDirectory()Opens in a new tab |
$ZU(18) = 0 | Undefined()Opens in a new tab |
$ZU(20) = USER | UserRoutinePath()Opens in a new tab |
$ZU(23,1) = 5 | |
$ZU(34) = 0 | |
$ZU(39) = USER | SysRoutinePath()Opens in a new tab |
$ZU(55) = 0 | LanguageMode()Opens in a new tab |
$ZU(56,0) = $Id: //iris/2018.1.1/kernel/common/src/emath.c#1 $ 0 | |
$ZU(56,1) = 1349 | |
$ZU(61) = 16 | |
$ZU(61,30,n) = 262160 | |
$ZU(67,10,$J) = 1 | JobTypeOpens in a new tab |
$ZU(67,11,$J) = glenn | UserNameOpens in a new tab |
$ZU(67,12,$J) = TRM: | ClientNodeNameOpens in a new tab |
$ZU(67,13,$J) = | ClientExecutableNameOpens in a new tab |
$ZU(67,14,$J) = | CSPSessionIDOpens in a new tab |
$ZU(67,15,$J) = 127.0.0.1 | ClientIPAddressOpens in a new tab |
$ZU(67,4,$J) = 0^0^0 | StateOpens in a new tab |
$ZU(67,5,$J) = %STACK | RoutineOpens in a new tab |
$ZU(67,6,$J) = USER | NamespaceOpens in a new tab |
$ZU(67,7,$J) = |TRM|:|5008 | CurrentDeviceOpens in a new tab |
$ZU(67,8,$J) = 923 | LinesExecutedOpens in a new tab |
$ZU(67,9,$J) = 46 | GlobalReferencesOpens in a new tab |
$ZU(68,1) = 0 | NullSubscripts()Opens in a new tab |
$ZU(68,21) = 0 | SynchCommit()Opens in a new tab |
$ZU(68,25) = 0 | |
$ZU(68,27) = 1 | |
$ZU(68,32) = 0 | ZDateNull()Opens in a new tab |
$ZU(68,34) = 1 | AsynchError()Opens in a new tab |
$ZU(68,36) = 0 | |
$ZU(68,40) = 0 | SetZEOF()Opens in a new tab |
$ZU(68,41) = 1 | |
$ZU(68,43) = 0 | OldZU5()Opens in a new tab |
$ZU(68,5) = 1 | BreakMode()Opens in a new tab |
$ZU(68,6) = 0 | |
$ZU(68,7) = 0 | RefInKind()Opens in a new tab |
$ZU(131,0) = MYCOMPUTER | |
$ZU(131,1) = MYCOMPUTER:IRIS | |
$ZV = IRIS for Windows (x86-64) 2018.1.0 (Build 527U) Tue Feb 20 2018 22:47:10 EST | $ZVERSION 特殊変数 |
スタックと変数の両方あるいはいずれかの出力
以下の動作を選択すると、出力デバイスを選択できます。
-
*P
-
*A
-
表示したい変数を選択した後に、*V
その他のデバッグ・ツール
デバッグ・プロセスで役立つツールが他にもあります。これには、以下のものがあります。
-
エラー・トラップ・ユーティリティ — %ETN および %ERN
$SYSTEM.OBJ.ShowReferences によるオブジェクトへの参照の表示
指定されたオブジェクトへの参照を格納したすべての変数をプロセスのシンボル・テーブルに表示するには、%SYSTEM.OBJOpens in a new tab クラスの ShowReferences(oref)Opens in a new tab メソッドを使用します。oref は指定されたオブジェクトの OREF (オブジェクト参照) です。OREF の詳細は、"OREF の基本" を参照してください。
エラー・トラップ・ユーティリティ
エラー・トラップ・ユーティリティ、%ETN と %ERN は、変数を格納し、エラーに関する他の適切な情報を記録することで、エラーの解析に役立ちます。
%ETN アプリケーション・エラー・トラップ
エラー・トラップを設定すると、アプリケーション・エラーの発生時、%ETN ユーティリティを実行できるため便利です。ユーティリティは、エラー時のジョブに関する重要な情報 (実行スタックや各変数の値など) を保存します。この情報はアプリケーションのエラー・ログに保存されており、%ERN ユーティリティを使用して表示するか、または管理ポータルの [アプリケーションエラーログの表示] ページ ([システムオペレーション]→[システムログ]→[アプリケーションエラーログ]) を使用して確認できます。
以下のコードを使用して、このユーティリティにエラー・トラップを設定します。
SET $ZTRAP="^%ETN"
プロシージャでは、外部ルーチンに $ZTRAP を設定できません。この制限のため、プロシージャでは ^%ETN を使用できません (プロシージャであるクラス・メソッドを含む)。ただし、%ETN を呼び出すローカル・ラベルには $ZTRAP を設定できます。
エラーが発生し、%ETN ユーティリティを呼び出すと、以下のようなメッセージが表示されます。
Error has occurred: <SYNTAX> at 10:30 AM
%ETN は HALT コマンド (プロセスを終了) で終了するため、アプリケーション・モードでルーチンを使用している場合にのみ、%ETN エラー・トラップを設定できます。ターミナル・プロンプトでは、エラーが発生したときに、ターミナルにエラーが表示され、デバッガ・プロンプトで直ちにエラーの分析を行えるので、便利です。以下のコードは、InterSystems IRIS がアプリケーション・モードの場合にのみ、エラー・トラップを設定します。
SET $ZTRAP=$SELECT($ZJ#2:"",1:"^%ETN")
%ERN アプリケーション・エラー・レポート
%ERN ユーティリティは、%ETN エラー・トラップ・ユーティリティによって記録されたアプリケーション・エラーを検証します。"%ERN を使用したアプリケーション・エラー・ログの表示" を参照してください。
以下のコードでは、すべての変数を *LOAD でロードしてからルーチンをロードすることを示すために、ルーチン REPORT の ZLOAD が発行されています。エラー発生時、DO に関する情報などを記録するプログラム・スタックが空でない場合、ジョブの状態を再現できます。
USER>DO ^%ERN
For Date: 4/30/2018 3 Errors
Error: ?L
1) "<DIVIDE>zMyTest+2^Sample.MyStuff.1" at 10:27 am. $I=|TRM|:|10044 ($X=0 $Y=17)
$J=10044 $ZA=0 $ZB=$c(13) $ZS=262144 ($S=268242904)
WRITE 5/0
2) <SUBSCRIPT>REPORT+4^REPORT at 03:16 pm. $I=|TRM|:|10044 ($X=0 $Y=57)
$J=10044 $ZA=0 $ZB=$c(13) $ZS=2147483647 ($S=2199023047592)
SET ^REPORT(%DAT,TYPE)=I
3) <UNDEFINED>zMyTest+2^Sample.MyStuff.1 *undef" at 10:13 pm. $I=|TRM|:|12416 ($X=0 $Y=7)
$J=12416 $ZA=0 $ZB=$c(13) $ZS=262144 ($S=268279776)
WRITE undef
Error: 2
2) <SUBSCRIPT>REPORT+4^REPORT at 03:16 pm. $I=|TRM|:|10044 ($X=0 $Y=57)
$J=10044 $ZA=0 $ZB=$c(13) $ZS=2147483647 ($S=2199023047592)
SET ^REPORT(%DAT,TYPE)=I
Variable: %DAT
%DAT="Apr 30 2018"
Variable: TYPE
TYPE=""
Variable: *LOAD
USER>ZLOAD REPORT
USER>WRITE
%DAT="Apr 30 2018"
%DS=""
%TG="REPORT+1"
I=88
TYPE=""
XY="SET $X=250 WRITE *27,*91,DY+1,*59,DX+1,*72 SET $X=DX,$Y=DY"
USER>