RPG

357. 対話式デバッグの開始

前回で障害エラーが発生したときにどのプログラムのどこで
どのような原因でエラーが発生したのかを突き止めることが
できた。

今回はそのエラーが発生するまでを追いかけて
エラーの解消を図りたい。

  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文を結合するロジックに原因があると判明した。

...このようにしてデバッグを進めていく。