RPG

376. RPGプログラムの障害の特定と回復の方法

RPGプログラムでアベンドと呼ばれるエラー・メッセージを
生じるエラーが発生したときの調査と原因の特定と回復の方法を
紹介する。
例えば実行中に次のようなエラーが発生して実行が中断したとする。

 (C G D F) 配列指標が範囲外になっている。      
                                               
                                               
  応答を入力して,実行キーを押してください。   
    応答 . . .                                 
                                               
                                               
 F3= 終了    F12= 取消し                       

このメッセージにすぐに応答してはいけない。
まずはこのエラーが出ている状態で現在の状況を調査することから始める。

(1)呼び出しスタックの表示

   

システム要求(SYS-REQ)を実行する。

                                 システム要求                           
                                                          システム :   Sxxxxxxx
 次の 1 つを選択してください。                                          
                                                                        
      1. 2 次ジョブのサインオンの表示                                   
      2. 前の要求の終了                                                 
      3. 現行ジョブの表示                                               
      4. メッセージ表示                                                 
      5. メッセージの送信                                               
      6. システム操作員メッセージの表示                                 
      7. ワークステーション・ユーザーの表示                             
                                                                        
     80. ジョブの切り離し                                               
                                                                        
     90. サインオフ         
                                            

オプション3.を選択してさらに呼出しスタックを調べる。

                                ジョブの表示                                   
                                                         システム :   Sxxxxxx 
ジョブ :   QPADEV0004     ユーザー :   QTR            番号 :   856962          
                                                                               
次の 1 つを選択してください。                                                  
                                                                               
     1. ジョブ状況属性の表示                                                   
     2. ジョブ定義属性表示                                                     
     3. ジョブ実行属性の表示(活動状態の場合)                                 
     4. スプール・ファイルの表示                                               
                                                                               
    10. ジョブ・ログ表示(活動状態,ジョブ待ち行列上,または保留中の場合)     
    11. 呼び出しスタックの表示(活動状態の場合)                               
    12. ロックの表示(活動状態の場合)                                         
    13. ライブラリー・リストの表示(活動状態の場合)                           
    14. オープンされたファイルの表示(活動状態の場合)                         
    15. ファイル一時変更の表示(活動状態の場合)                               
    16. コミットメント制御状況の表示(活動状態の場合)                         
                                                                      続く ... 
選択項目                                                                       
                                                                               
                                                                               
F3= 終了   F12= 取り消し                                                       

(2) 「11. 呼び出しスタックの表示」を選択する。

                           呼び出しスタックの表示                             
                                                         システム :   Sxxxxxx
ジョブ :   QPADEV0001     ユーザー :   QTR            番号 :   856959         
スレッド:   00000007                                                             
                                                                              
                                                                              
タイプ   プログラム              ステートメント            プロシージャー              
      QCMD       QSYS                     /0517                               
      QUICMENU   QSYS                     /00C1                               
   1  QUIMNDRV   QSYS                     /060F                               
   2  QUIMGFLW   QSYS                     /04D7                               
   3  QUICMD     QSYS                     /056E                               
   4  QCMD       QSYS                     /01C8                               
      DBG001     TEST.COM                        _QRNP_PEP_DBG001             
      DBG001     TEST.COM      19                DBG001                       
      QRNXIE     QSYS          11                _QRNX_G_FC_H                 
      QRNXIE     QSYS          2                 _QRNX_DFT_ERROR              
      QRNXIE     QSYS          17                _QRNX_INQ                    
      QRNXIE     QSYS          16                IトヌMヘキ                       
      QMHSNDPM   QSYS                     /0ADF                               
                                                                      続く ...
F3= 終了         F5= 最新表示   F11= 活動化グループの表示   F12= 取り消し     
F16=ジョブ・メニュー   F17= 先頭      F18= 最後   F22= フィールド全体の表示         

(3) コンパイル・リストを確認する。

エラーの箇所のステートメントは(2)で 19 とわかっているのでそのステートメントの実行は

 行    <----------------------  ソースの仕様 ------------------------------------>
 番号  ....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
                           ソ ー ス ・ リ ス ト                             
     1 H DFTNAME(DBG001) DATEDIT(*YMD/) BNDDIR('QC2LE')                           
     2 F********** 配列指標をオーバーするエラー ******************************    
     3 F*                                                                         
     4 F**********************************************************************    
     5                                                                            
     6  * CRTRPGMOD  OBJ(QTEMP/DBG001)   SRCFILE(R610SRC/QRPGLESRC)               
     7  * DBGVIEW(*SOURCE) AUT(*ALL)                                              
     8  * CRTPGM PGM(ASNET.COM/DBG001) MODULE(QTEMP/DBG001) ACTGRP(*NEW)          
     9  *        AUT(*ALL)                                                        
    10                                                                            
    11  *-------------------------------------------------------------------*     
    12  *  2020/09/07 : 作成                                                      
    13  *-------------------------------------------------------------------*     
  14  *( 作業変数 
   15 D AR              S              1A   DIM(10)                               
   16 D N               S              4S 0                                       
   17                                                                             
   18 C     1             DO        12            N                          
   19 C                   MOVE      '*'           AR(N)                      
   20 C                   ENDDO                                              
   21 C                   SETON                                        LR----
   22 C                   RETURN                                             
      * * * * * *   ソ ー ス の 終 わ り  * * * * * *                  

によって

    19 C                   MOVE      '*'           AR(N)

であることがわかる。
  従ってフィールド値 :N の値を調べればよいことがわかる。

(4) エラーに対して D (=Dump)で応答する。

(5) ダンプ・リストを調べる。

WRKOUTQ QEZDEBUG で最後に出力されているスプールが(4)で出力されたプログラムの
ダンプ・リストであるのでこの中でフィールドの値を調べる。

                                                   スプール・ファイルの表示 
ファイル . . . :   QPPGMDMP                                                 
制御 . . . . . .                                                            
検索 . . . . . .                                                            
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+.
                                                                            
 ILE RPG 定様式ダンプ                                                       
  プログラム状況域 :                                                        
  プロシージャー名  . . . . . . . . . . :   DBG001                          
  プログラム名  . . . . . . . . . . . . :   DBG001                          
     ライブラリー . . . . . . . . . . . :   TEST.COM                        
  モジュール名  . . . . . . . . . . . . :   DBG001                          
  プログラム状況  . . . . . . . . . . . :   00121                           
              (C G D F) 配列指標が範囲外になっている。                      
  直前の状況  . . . . . . . . . . . . . :   00000                           
  エラーのステートメント  . . . . . . . :   00000019                        
  RPG ルーチン  . . . . . . . . . . . . :   *DETC                           
  パラメーターの数  . . . . . . . . . . :                                   
  メッセージ・タイプ  . . . . . . . . . :   MCH                             
  追加のメッセージ情報  . . . . . . . . :   0603                            
  メッセージ・データ  . . . . . . . . . :                                   
               添え字値または文字列の範囲エラー。                           
   :
   :
NAME                  ATTRIBUTES           VALUE                        
AR                    CHAR(1)              DIM(10)                      
                        (1-10)             '*'              '5C'X       
N                     ZONED(4,0)           0011.            'F0F0F1F1'X 
            * * * * *   RPG ダンプの終わり   * * * * *                  

N の値は 11 であり配列ARの配列の数 10 をオーバーしたことがわかる。

(6) フィールドの異常値の原因を調べて解決する

 

ダンプ・リストでフィールドに異常値が見つかったら

  ・異常値になる原因がある。
    ・異常値ではないがプログラムがその値に考慮されていなかった。

などの原因が考えられる。
 プログラムを異常値が発生しないように修正するかまたは
その値にも対応するようにプログラムを修正して再コンパイルする。

(7) 修正後に実行してエラーが発生しないことを確認する。

  

エラーの原因は修正して正しく実行することができることを確かめる。
エラーの原因であると確定できるのは修復して正しく実行できることを
確認して初めてそれがエラーの原因であったと断定することができる。
  正しく回復できるまではエラーの原因であるとは言えない。

ここで行ったのは

    ・エラー行を特定する
       ・エラー行でのフィールドの値を調べる
       ・プログラムのロジックを再検討する

という方法であった。エラーの場所と内容を調査することから始めないと
原因を特定することはできない。

 

—誤った考え方

  

エラーが発生したときに「○○ のエラーが発生するのは○○が原因である」とか
○○ のエラーが発生するのは何が原因ですか?」のように
調べもせずにエラーの原因をひとつだけだけであると類推する考えは全くの誤りである。
エラーの原因は必ずしもひとつではないしエラーと原因は 1対1の関係にはない。
論理的な思考ができない人にこのような傾向がある。
本が床に落ちた原因は人手によるかもしれないし地震かも知れない。
   物事が起きる原因はいくつもあるのに原因はただ一つと考えているのは
全くの誤りであるし論理的な思考とは言えない。
   デバッグほど論理的思考が試される場面はない。
慌てて原因を特定したがるのではなく論理的にジックリと思考して欲しい。