導入
COBOL開発において、可変長レコードを扱う際に欠かせないのがOCCURS句のDEPENDING ON指定(いわゆるODO)です。しかし、ODO項目を定義した直後に別のデータ項目を配置すると、その項目の物理的なアドレスが実行時の数値によって変動します。この構造は、一見便利ですが、メモリ上の位置が固定されないため、デバッグの難易度を上げ、最悪の場合は予期せぬデータ破壊を招くリスクを孕んでいます。本記事では、この「ODO後続項目」の仕組みと、実務で安全に扱うためのポイントを解説します。
基礎知識
ODOとは、DEPENDING ON句を使って、レコードの長さや繰り返しの回数を実行時に可変させる仕組みです。通常、可変項目はレコードの末尾に配置するのが定石ですが、業務要件によっては「可変項目の後に、さらに固定項目を置きたい」というケースが存在します。
コンパイラは、ODO項目の後に続く項目のアドレスを計算する際、実行時に「現在のOCCURS回数」を参照してオフセットを算出します。つまり、プログラム実行中にODO変数の値が変わると、後続項目のメモリ上の位置もシフトします。この「アドレスの動的算出」こそが、パフォーマンス低下やバグの温床となる要因です。
実装/解決策
実務で安全に実装するための鉄則は、「後続項目が必要な場合は、REDEFINESを使用して別領域として扱う」か、「構造を工夫して後続項目を独立させる」ことです。どうしても直後に配置せざるを得ない場合は、必ず領域の再定義(REDEFINES)を行い、コンパイラがオフセット計算で迷わないようなデータ定義を心掛けます。
サンプルプログラム
以下に、ODO項目を伴うレコードの定義例と、安全なアクセス方法を示します。
01 WORK-RECORD.
05 ITEM-COUNT PIC 9(02).
05 TABLE-DATA OCCURS 1 TO 10 TIMES
DEPENDING ON ITEM-COUNT.
10 TABLE-VALUE PIC X(05).
> 以下のフィールドは、ITEM-COUNTの値によって格納アドレスが変わる
05 FOLLOWING-ITEM PIC X(10).
PROCEDURE DIVISION.
> 1. ODO項目に値をセット
MOVE 3 TO ITEM-COUNT.
> 2. 後続項目へ値をセット(コンパイラがアドレスを再計算する)
MOVE “FIXED-VAL” TO FOLLOWING-ITEM.
> 3. 確認:読み取り時は常に正しいアドレスを指しているか注意が必要
DISPLAY “後続項目の値: ” FOLLOWING-ITEM.
STOP RUN.
応用・注意点
現場で最も注意すべきは、「ODO項目を含むレコードを外部ファイル(順ファイル等)に書き出す際、コンパイラによってレコード長が固定長として扱われるか可変長として扱われるか」という点です。
1. 再定義の活用: ODO項目の後に重要な項目を置く場合は、可能な限りREDEFINES句を用いて、可変部分と固定部分を論理的に分離してください。これにより、アドレス計算の曖昧さを排除できます。
2. パフォーマンス: 頻繁にアクセスするループ内でODO後続項目を参照すると、そのたびにアドレス計算のオーバーヘッドが発生します。重要な処理では、一度固定領域へ転送してから処理する工夫が必要です。
3. 移植性のリスク: ベンダーによって、ODO項目が最大値で領域を確保するのか、最小値で確保するのかが異なる場合があります。異なるプラットフォームへの移行を想定する場合、この複雑なデータ構造は避けるのが賢明です。
「動的な構造」は強力な武器ですが、保守担当者を悩ませる種にもなります。設計段階で「本当にこの構造が必要か?」を今一度問い直し、可能であればシンプルな構造への変更を検討してください。

コメント