前回で障害エラーが発生したときにどのプログラムのどこで
どのような原因でエラーが発生したのかを突き止めることが
できた。
今回はそのエラーが発生するまでを追いかけて
エラーの解消を図りたい。
225 C LEN SUBST SELECT_:N FROM_
前回の調査ではこのステートメントでエラーが発生し
原因は LENが -24 であったことにある。
また同時にこのときの N は 326 というかなり大きな値であり
これも原因になる可能性がある。
そこでなぜ LEN = -24 という値になってしまったのかを
対話式デバッグによって追いかけていきたい。
デバッグの前にエラー発生の前のソースを見てみると
0206.00 C****************************************************** 0207.00 C PARSE BEGSR 0208.00 C****************************************************** 0209.00 C MOVE *BLANKS WHERE_ 0210.00 C MOVE *BLANKS ON_ 0211.00 C 'FROM ' SCAN SELECT_:1 N 50 0212.00 C *IN50 IFEQ *ON 0213.00 C N SUB 1 LEN 0214.00 C LEN SUBST SELECT_:1 SELEC_ 0215.00 C 'WHERE ' SCAN SELECT_:1 M 50 0216.00 C *IN50 IFEQ *ON 0217.00 C EVAL LEN = M - N 0218.00 C LEN SUBST SELECT_:N FROM_ 0219.00 C MOVEA SELECT_ AR 0220.00 C MOVEA(P) AR(M) WHERE_ 0221.00 C ENDIF 0222.00 C 'ON ' SCAN SELECT_:1 M 50 0223.00 C *IN50 IFEQ *ON 0224.00 C EVAL LEN = M - N 0225.00 C LEN SUBST SELECT_:N FROM_ 0226.00 C MOVEA SELECT_ AR 0227.00 C MOVEA(P) AR(M) ON_ 0228.00 C ENDIF 0229.00 C ENDIF 0230.00 C ENDSR
となっており
0224.00 C EVAL LEN = M - N
によって
LEN = M – N
と計算されている。そこで M の値もダンプ・リストによって調べてみると
M ZONED(4,0) 0302. 'F0F3F0F2'X N ZONED(4,0) 0326. 'F0F3F2F6'X
であり Mの値が N より小さいので LENが結果として負の値となり
エラーが発生しているようである。
そこでこの一連の演算が正しいのかを対話式デバッグによって
追いかけることにする。
プログラムとはプログラムだけで動作するのではなく
・プログラム
・操作
・データ
・環境
の4つの要素から成り立っていることを忘れてはいけない。
このように動作するはずだ、と予想して開発したはずのプログラムも
予想意外の
・操作
・データ
・環境
の場合に考慮されていない事態となってしまう。
このことをしっかり考慮してデバッグを開始するものとする。
[対話式デバッグの開始]
デバッグの開始は STRDBG(デバッグ開始)コマンドによって開始するのだが
ソース・デバッグを行うにはコンパイルには次のようにデバッグ・ビューを
*SOURCE として指定してコンパイルしておく必要がある。
CRTBNDRPG PGM(V.PANELWKR/APPHLPEXT) SRCFILE(R610SRC/QRPGLESRC) DFTACTGRP(*NO) ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)
それでは
STRDBG PGM(V.PANELWKR/ADDHLPEXT) UPDPROD(*YES)
によって対話式デバッグを開始すると次のようにソースがデバッガーによって
表示される。
調査を開始したいサブ・ルーチンの先頭にカーソルをセットして
F6キーを押すとデバッグの停止点が次のようにセットされる。
必要であればいくつかの停止点を同じように設けておいてから
通常の呼び出しとしてプログラムを開始する。
すると停止点に到達するとデバッガーは次のように停止する。
当然のことなのだがデバッグを進めるに当たっては操作や環境を
変えてはならない。
操作のために入力する値も同じ値を繰返し入力するように
しなければならない。
さて停止点に到達したら F10キーで 1ステップずつ実行を
進めていくことができる。
もちろん F6キーを押して新たな停止点を追加することができる。
F12キーを押せば次の停止点まで一挙に進むことができる。
ここでは 211行目までF10キーで進めたところで
フィールド: SELECT_の値を調べてみよう。
それには次のように EVAL SELECT_ とデバッグ行に入力する。
ここからもちょっとしたテクニックであるがこのように調べた値は
メモ帳などに記録しておくほうがよい。
時々見かけるのはデバッグの都度に異なる操作や違ったデータを
入力する人がいるがそれでは原因の追究は望めない。
前回に説明したようにプログラムは
・プログラム
・データ
・操作
・環境
の4つの要素を基盤として動いている。デバッグのたびにこれらの
いくつかを変更したのでは変更したことが原因となる可能性も
出てきてしまう。
デバッグ中は絶対にデータ・操作・環境は変えてはならない。
さてこの演算を見ていると SELECT_ の中に FROM という文字列を探して
その直前までの文字列を取り出して SELEC_ に入れている。
次に WHERE という文字列を SELECT_の中から探して FROM …という記述だけを
FROM_ に入れようとしている。
ここでEVAL N でNの値を調べてみると N=14 で異常値ではない。
M も M=36 で結果として LEN = 22 であり障害は発生していない。
このままデバッグを継続してもよいのだがデバッグの調査を早めるために
このRPGソースを次のように修正してコンパイルした。
0224.00 C EVAL LEN = M - N 0225.00 C IF LEN < 0 0226.00 C SETOFF 50 0227.00 C ENDIF 0228.00 C LEN SUBST SELECT_:N FROM_ 0229.00 C MOVEA SELECT_ AR 0230.00 C MOVEA(P) AR(M) ON_
次の3行をデバッグのために追加した。
0225.00 C IF LEN < 0 0226.00 C SETOFF 50 0227.00 C ENDIF
LEN が負の値のときに障害となるので逆に LEN < 0のときだけの 停止点を作るためである。
デバッグしてみると見事に上のように LEN<0のときでデバッグが停止した。 このときの N = 326 M = 302 LEN = -24
このSELECT_の文字列を見てみると
ON T02.TACODE=T01.JUTANT FROM QTRFIL/JUCHU T01 ....
とあるように FROM より ON のほうが前に位置していることがわかった。
これは SELECT文を結合するロジックに原因があると判明した。
...このようにしてデバッグを進めていく。