導入
COBOLの「ODO (OCCURS DEPENDING ON)」句は、データ量を動的に制御できる非常に強力な機能です。しかし、実務で多くのエンジニアが陥りがちなのが、「最大値」と「現在値」のメモリ占有に関する誤解です。特に、大規模なオンライン処理や、ファイル入出力時のバッファ最適化において、この挙動を理解していないと不要なメモリ消費や意図しないバイナリデータが混入するリスクがあります。今回は、この「残り領域」をどう制御すべきかについて解説します。
基礎知識
ODO句は「OCCURS 1 TO N TIMES DEPENDING ON データ名」のように記述します。ここで重要なのは、メモリ上では常に「N(最大値)」分の領域が静的に確保されるという点です。
例えば「OCCURS 1 TO 100」と定義した場合、プログラム実行時には100個分の配列領域が確保されます。現在値(DEPENDING ONで指定した変数)が10であっても、後ろの90個分は「予約済み」としてメモリ上に存在し続けます。WRITE文で書き出す際は現在値までの長さが書き出されますが、メモリダンプを取ると、残りの領域には前回の処理のゴミ(残留データ)が残っていることがよくあります。
実装/解決策
実務で最も注意すべきは、再利用時の「初期化漏れ」です。特に、ある処理で最大値までデータを入れた後に、別の処理で少ないデータ数をセットする場合、後ろの領域に古いデータが残ったままになります。
これを防ぐには、データをセットする直前に、テーブル全体(あるいは使用する範囲)をスペースやゼロで初期化する、あるいは書き出し時に「書き出す長さ」を厳密に制御する仕組みが必要です。
サンプルプログラム
以下のコードは、ODOテーブルを安全に再利用するための初期化例です。
IDENTIFICATION DIVISION.
PROGRAM-ID. ODO-CONTROL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TBL-CONTROL.
05 TBL-COUNT PIC 9(03).
01 SAMPLE-TABLE.
05 ITEM-DATA OCCURS 1 TO 100 TIMES
DEPENDING ON TBL-COUNT
PIC X(10).
PROCEDURE DIVISION.
- — 1. データのセット —
MOVE 5 TO TBL-COUNT.
PERFORM VARYING TBL-COUNT FROM 1 BY 1 UNTIL TBL-COUNT > 5
MOVE “DATA-SET” TO ITEM-DATA(TBL-COUNT)
END-PERFORM.
- — 2. 再利用前の安全な初期化 —
- 現在値が減る場合に備え、最大値までをクリアする手法
PERFORM VARYING TBL-COUNT FROM 1 BY 1 UNTIL TBL-COUNT > 100
MOVE SPACES TO ITEM-DATA(TBL-COUNT)
END-PERFORM.
- 新しい現在値を設定
MOVE 3 TO TBL-COUNT.
STOP RUN.
応用・注意点
現場でよくあるバグとして、「可変長ファイルへの書き出し時に、意図せずゴミデータが含まれる」というケースがあります。これは、WRITEする際に、DEPENDING ONの値が正しく更新されていない、あるいはメモリ上の直前までの値がバッファに残っていることが原因です。
特に、MOVE CORRESPONDINGなどを使用する場合、ODO項目が含まれると予期せぬ領域までコピーされるリスクがあるため、ODO項目を含むグループ転送には細心の注意を払ってください。
また、パフォーマンスを優先して「初期化をサボる」と、のちにデバッグ不可能な障害を招きます。「ODOを使用する際は、必ずDEPENDING ONの変数を更新した直後に有効範囲を確定させる」というルールを徹底することをお勧めします。

コメント