[COBOLのはじめ方] Part21: エラーハンドリングとデバッグ方法

COBOL

はじめに

COBOLプログラムを作成する上で、予期せぬエラーへの対応と、問題発生時の原因究明(デバッグ)は避けて通れない重要なスキルです。どんなに注意深くコーディングしても、データの不整合や予期しない操作、あるいは単純なコーディングミスによってエラーが発生する可能性があります。

このセクションでは、COBOLプログラムにおける代表的なエラーハンドリングの方法と、デバッグを効率的に進めるための基本的な手法について学びます。しっかりとしたエラー処理とデバッグスキルを身につけることで、より堅牢で信頼性の高いプログラムを作成できるようになります 💪。

エラーハンドリング

エラーハンドリングとは、プログラム実行中に発生する可能性のあるエラーを事前に予測し、それに対応する処理を組み込んでおくことです。これにより、エラーが発生してもプログラムが異常終了するのを防いだり、エラーの原因を特定しやすくしたりできます。

エラーの種類

COBOLプログラムで遭遇する可能性のあるエラーは、大きく分けて以下の種類があります。

  • コンパイルエラー: ソースコードの文法的な誤りなど、コンパイル時に検出されるエラー。コンパイラがエラーメッセージを出力します。
  • 実行時エラー: プログラムの実行中に発生するエラー。ゼロ除算、不正なデータ形式、ファイルアクセスエラーなどが該当します。
  • 論理エラー: プログラムは正常に動作しているように見えるが、意図した結果と異なる結果になるエラー。コーディングのロジック(考え方)の誤りが原因です。

エラーハンドリングは主に実行時エラーへの対策として重要ですが、論理エラーの発見にも役立つことがあります。

COBOLにおけるエラーハンドリング構文

COBOLには、特定のエラー状況に対応するための構文が用意されています。

ON SIZE ERROR (算術演算エラー)

ADD, SUBTRACT, MULTIPLY, DIVIDE, COMPUTE といった算術演算命令で、演算結果が結果を格納する変数の桁数を超えてしまう(桁あふれ)場合や、ゼロ除算が発生した場合に、指定した処理を実行します。


COMPUTE WS-RESULT = WS-VALUE1 / WS-VALUE2
    ON SIZE ERROR
        DISPLAY "エラー: 演算結果が大きすぎるか、ゼロ除算が発生しました。"
        MOVE 9999 TO WS-ERROR-CODE
        PERFORM ERROR-ROUTINE
END-COMPUTE.
      

INVALID KEY (ファイルアクセスエラー)

索引ファイル(Indexed file)や相対ファイル(Relative file)に対する READ, WRITE, REWRITE, DELETE, START 命令で、キーの重複、存在しないキーの指定などのエラーが発生した場合に、指定した処理を実行します。


READ CUSTOMER-FILE KEY IS CUSTOMER-ID
    INVALID KEY
        DISPLAY "エラー: 指定された顧客ID " CUSTOMER-ID " は存在しません。"
        MOVE 10 TO WS-FILE-ERROR-CODE
        PERFORM FILE-ERROR-ROUTINE
END-READ.

WRITE NEW-RECORD
    INVALID KEY
        DISPLAY "エラー: キー " NEW-RECORD-KEY " は既に存在します。"
        MOVE 22 TO WS-FILE-ERROR-CODE
        PERFORM FILE-ERROR-ROUTINE
END-WRITE.
      

NOT INVALID KEY 句を併用することで、エラーが発生しなかった場合の処理も記述できます。

AT END (ファイル終端)

順編成ファイル(Sequential file)を READ 命令で読み進め、ファイルの終わりに達した場合(次のレコードが存在しない場合)に、指定した処理を実行します。


READ INPUT-FILE
    AT END
        SET WS-EOF-FLAG TO TRUE
        DISPLAY "ファイルの終わりに達しました。"
END-READ.
      

NOT AT END 句を併用することで、ファイルの終わりに達していない場合の処理も記述できます。

ON OVERFLOW (文字列操作エラー)

STRING 命令や UNSTRING 命令で、結果を格納する変数の領域を超えてしまう場合に、指定した処理を実行します。


STRING WS-PART1 DELIMITED BY SIZE
       WS-PART2 DELIMITED BY SPACE
       INTO WS-FULL-STRING
    ON OVERFLOW
        DISPLAY "エラー: 結合結果が格納領域を超えました。"
        MOVE 30 TO WS-STRING-ERROR-CODE
END-STRING.
      

FILE STATUS句の活用

ファイル操作に関するより詳細なエラー情報を得るためには、FILE STATUS句を使用します。SELECT句でファイルごとにファイル状態を格納する変数を指定し、各ファイルI/O命令実行後にその変数の値を確認することで、成功か失敗か、失敗した場合はその原因を特定できます。


ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT MY-FILE ASSIGN TO "MYDATA.DAT"
           ORGANIZATION IS INDEXED
           ACCESS MODE IS DYNAMIC
           RECORD KEY IS MY-KEY
           FILE STATUS IS WS-MY-FILE-STATUS.  *> ファイル状態を格納する変数を指定

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-MY-FILE-STATUS      PIC XX.
   88 FILE-OK             VALUE "00".
   88 FILE-EOF            VALUE "10".
   88 FILE-DUP-KEY        VALUE "22".
   88 FILE-NOT-FOUND      VALUE "23".
   88 FILE-DISK-FULL      VALUE "30". *> 環境依存の場合あり
   88 FILE-NOT-OPEN       VALUE "41". *> 環境依存の場合あり

PROCEDURE DIVISION.
OPEN-FILE-RTN.
    OPEN I-O MY-FILE.
    IF NOT FILE-OK
        DISPLAY "ファイルオープンエラー: " WS-MY-FILE-STATUS
        *> エラー処理
    END-IF.

READ-FILE-RTN.
    READ MY-FILE KEY IS SEARCH-KEY
        INVALID KEY
            IF FILE-NOT-FOUND
                DISPLAY "レコードが見つかりません: " WS-MY-FILE-STATUS
            ELSE
                DISPLAY "READ INVALID KEYエラー: " WS-MY-FILE-STATUS
            END-IF
        NOT INVALID KEY
            DISPLAY "レコード読み込み成功"
    END-READ.

WRITE-FILE-RTN.
    WRITE MY-RECORD
        INVALID KEY
            IF FILE-DUP-KEY
                DISPLAY "キー重複エラー: " WS-MY-FILE-STATUS
            ELSE
                DISPLAY "WRITE INVALID KEYエラー: " WS-MY-FILE-STATUS
            END-IF
        NOT INVALID KEY
            DISPLAY "レコード書き込み成功"
    END-WRITE.

CLOSE-FILE-RTN.
    CLOSE MY-FILE.
    IF NOT FILE-OK
        DISPLAY "ファイルクローズエラー: " WS-MY-FILE-STATUS
    END-IF.
      

FILE STATUS句で受け取るコードの値とその意味は、使用しているCOBOL処理系(コンパイラや実行環境)によって異なる場合があります。代表的なコードを以下に示しますが、詳細は利用環境のマニュアルを確認してください。

ファイル状態コード 主な意味 (ANSI COBOL準拠) 補足
00 正常終了 操作が成功したことを示します。
10 ファイルの終端 (AT END) 順次読み込みでファイルの最後に到達しました。
21 キー順序エラー (Sequence Error) 索引ファイルなどで、書き込もうとしたレコードのキー順が不正です。
22 キー重複エラー (Duplicate Key) 一意キー制約のあるファイルに、既に存在するキーを持つレコードを書き込もうとしました。
23 レコード未存在エラー (Record Not Found) 指定されたキーを持つレコードが存在しません。
24 ディスク領域不足 (Disk Space Full / Boundary Violation) ファイルの書き込み中にディスクスペースがなくなりました。または、ファイルの境界を超えて書き込もうとしました。
30 永続エラー (Permanent Error) ハードウェアエラーなど、回復不能なI/Oエラーが発生しました。多くの場合、追加情報が付与されます。
35 ファイル未存在 (File Not Found) OPENしようとしたファイルが存在しません。
39 ファイル属性不一致 (File Attribute Conflict) プログラムで定義したファイル属性(編成、レコード長など)と実際のファイル属性が一致しません。
41 ファイルオープン済み (File Already Open) 既に開いているファイルをOPENしようとしました。
42 ファイル未オープン (File Not Open) 閉じていないファイルをCLOSEしようとしました。
43 READ後でないDELETE/REWRITE (DELETE/REWRITE not preceded by READ) 順次アクセスモードで、READ命令の直後以外でDELETEやREWRITEを実行しようとしました。
44 レコード長/キー不一致 (Record length / Key mismatch) 書き込もうとしたレコード長が不正、またはキー項目が一致しません。
46 READエラー (Read Error) 有効な次のレコードがない状態でREADを実行しようとしました(EOF後など)。
47 ファイルアクセス権エラー (File Access Denied) READ権限のないファイルにREADしようとした、など。
48 書き込み権限エラー (Write Access Denied) WRITE権限のないファイルにWRITEしようとした、など。
49 レコードロックエラー (Record Locked) 他のプロセスによってロックされているレコードにアクセスしようとしました。
9x 処理系依存のエラー 1桁目が’9’の場合、COBOL処理系固有のエラーを示します。2桁目以降で詳細なエラーコードが示されることが多いです。

注意: 上記は代表例です。必ず使用しているCOBOL処理系のマニュアルで正確なコードと意味を確認してください。

ファイル状態コードは2バイトで構成され、1バイト目でエラーの大分類、2バイト目で詳細を示します。FILE STATUS変数を使ってこれらのコードを受け取り、プログラム内で適切なエラー処理を行うことが重要です。

デバッグ方法

デバッグとは、プログラムに含まれるエラー(バグ)を見つけ出し、修正する作業のことです。エラーハンドリングでエラーの発生自体を検知できても、その根本原因を特定するにはデバッグ作業が必要になります。

基本的なデバッグの流れ

  1. 問題の再現: どのような操作やデータでエラーが発生するのか、確実に再現できる手順を見つけます。
  2. 原因箇所の特定: プログラムのどこで問題が発生しているのかを絞り込みます。
  3. 原因の分析: なぜそこで問題が発生するのか、変数の中身や処理の流れを追跡して原因を突き止めます。
  4. 修正: 特定した原因を取り除くようにコードを修正します。
  5. 再テスト: 修正によって問題が解決したか、また、修正によって新たな問題が発生していないかを確認します。

COBOLにおけるデバッグ手法

DISPLAY文によるトレース

最も基本的で手軽なデバッグ手法は、DISPLAY文を使って変数の中身やプログラムの実行経路をコンソールやログファイルに出力することです。


*> 変数の値を表示
DISPLAY "処理開始: KEY=" SEARCH-KEY ", COUNT=" WS-COUNTER.

PERFORM PROCESS-RECORD.

*> 特定の処理ブロックを通ったことを表示
DISPLAY "PROCESS-RECORD 完了".

IF WS-ERROR-FLAG = TRUE
    *> エラー発生時の情報を表示
    DISPLAY "エラー検出: ERROR-CODE=" WS-ERROR-CODE
END-IF.
      

DISPLAY文を要所要所に埋め込むことで、処理の流れや変数の変化を追いやすくなります。ただし、デバッグ目的で追加したDISPLAY文は、最終的なプログラムからは削除するか、コメントアウトするのを忘れないようにしましょう。

GnuCOBOLなど一部の処理系では、デバッグ行(標識領域(7桁目)に ‘D’ を記述)を利用できます。デバッグモードでコンパイルした場合のみ、この行が有効になります。


       IDENTIFICATION DIVISION.
       PROGRAM-ID. DEBUG-SAMPLE.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER. GnuCOBOL.
       OBJECT-COMPUTER. GnuCOBOL.
      *SOURCE-COMPUTER. GnuCOBOL WITH DEBUGGING MODE. *> デバッグモード有効化 (例)
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-COUNT PIC 9(3) VALUE 0.
       PROCEDURE DIVISION.
       MAIN-PARA.
           DISPLAY "通常処理開始".
D          DISPLAY "*** デバッグモード時のみ表示 ***". *> 標識領域(7桁目)にD
           ADD 1 TO WS-COUNT.
D          DISPLAY "WS-COUNT = " WS-COUNT.
           DISPLAY "通常処理終了".
           STOP RUN.
      

GnuCOBOLでは、コンパイル時に `-fdebugging-line` オプションを指定すると、デバッグ行が有効になります。

デバッガの利用

より高度なデバッグには、デバッガ (Debugger) と呼ばれるツールを使用します。デバッガを使うと、以下のようなことが可能になります。

  • ブレークポイントの設定: プログラムの特定の行で実行を一時停止させる。
  • ステップ実行: プログラムを一行ずつ実行させる(ステップイン、ステップオーバー、ステップアウト)。
  • 変数/メモリの監視: 実行中の変数の値やメモリの内容を確認・変更する。
  • コールスタックの確認: プログラムの呼び出し階層を確認する。

使用できるデバッガは、開発環境(OS、COBOL処理系)によって異なります。

  • GnuCOBOL: GDB (GNU Debugger) と連携できます。コンパイル時に -g オプションを付加するとデバッグ情報が埋め込まれます。別途、GDB用のCOBOL拡張機能(例: VSCodeの拡張機能など)があると、よりCOBOLの変数などを扱いやすくなります。
  • 商用COBOL (NetCOBOL, Micro Focus COBOLなど): それぞれ専用の対話型デバッガが提供されていることが多いです。IDE(統合開発環境)に組み込まれている場合もあります。

デバッガの具体的な使用方法はツールによって異なりますので、各ツールのドキュメントを参照してください。

コンパイラオプションの活用

コンパイラには、デバッグに役立つオプションが用意されていることがあります。

  • デバッグ情報付加: GnuCOBOLの -g オプションのように、デバッガが利用するための情報を実行ファイルに埋め込みます。
  • 実行時チェック強化: GnuCOBOLの --debug (または -d) オプションのように、配列の添え字範囲チェックや数値項目のデータ形式チェックなどを実行時に行い、エラーを検出しやすくします。
  • トレース機能: 実行した命令の履歴を出力する機能(例: NetCOBOLのTRACE機能)。
  • カバレッジ情報: プログラムのどの部分が実行されたか(網羅率)を出力する機能。テストの十分性を確認するのに役立ちます。

どのようなオプションが利用可能かは、使用しているコンパイラのマニュアルを確認してください。

エラーメッセージとダンプの分析

プログラムが異常終了(Abend)した場合、OSやCOBOLランタイムがエラーメッセージやメモリダンプを出力することがあります。これらの情報を読み解くことで、エラーの原因特定の手がかりが得られます。

  • エラーメッセージ: エラーの種類や発生箇所を示すコードやメッセージが出力されます。
  • メモリダンプ: エラー発生時のメモリの内容が出力されます。変数の中身などを確認できますが、読み解くには知識と経験が必要です。

特にメインフレーム環境では、ダンプ解析が重要なデバッグ手法となります。

まとめ

エラーハンドリングとデバッグは、プログラム開発において非常に重要です。適切なエラー処理を実装することでプログラムの安定性を高め、デバッグ手法を習得することで問題解決の効率を上げることができます。

  • ON SIZE ERROR, INVALID KEY, AT END, ON OVERFLOW などの構文で特定のエラーを検知する。
  • FILE STATUS句を使って、ファイル操作の詳細な結果を取得し、エラー処理を行う。
  • DISPLAY文で処理の流れや変数の値を確認する。
  • デバッガを活用して、ステップ実行やブレークポイント、変数監視を行う。
  • コンパイラオプションやエラーメッセージ、ダンプ情報を活用する。

これらの手法を状況に応じて使い分け、粘り強く問題に取り組むことが、COBOLプログラマとしてのスキルアップに繋がります🚀。

参考情報

  • GnuCOBOL Documentation:
    • GnuCOBOL Programmer’s Guide (英語ですが、詳細な情報が記載されています): URLはバージョンにより異なる可能性があるため、公式サイト等で確認してください。
    • GnuCOBOL マニュアル: GnuCOBOLのコンパイラオプション(–debug, -g)などが説明されています。
  • IBM COBOL for z/OS Documentation (メインフレームCOBOLの例):
    • Language Reference (言語仕様): 各構文 (INVALID KEY, AT ENDなど) の詳細な説明があります。
    • Programming Guide (プログラミングガイド): FILE STATUSコードやエラー処理戦略について解説されています。
  • Micro Focus COBOL Documentation (分散系COBOLの例):
    • Language Reference / Programming Guide: 同様に、エラーハンドリングやファイルステータスに関する情報が含まれます。
  • ファイルステータスコード一覧の例:

💡 ヒント: 「COBOL FILE STATUS コード一覧」や「COBOL (処理系名) デバッグ 方法」といったキーワードで検索すると、さらに多くの情報が見つかります。

コメント

タイトルとURLをコピーしました