導入
COBOLのBASED項目とポインタ(ADDRESS OF)は、C言語の構造体ポインタのようにメモリ上の任意のアドレスを特定のレイアウトにマッピングできる強力な機能です。しかし、この機能は「型安全性の欠如」という諸刃の剣でもあります。本稿では、動的構造体を扱う際に直面する「意味的な整合性」の課題と、それを防ぐための現場の実践的な知恵を共有します。
基礎知識
COBOLにおけるBASED項目とは、固定メモリを占有せず、明示的にSET文でアドレスを割り当てるまでデータとして実体を持たない項目です。
・ADDRESS OF [データ名]: その項目のメモリ開始アドレスを取得します。
・SET [BASED項目] TO ADDRESS OF [参照先]: 特定のアドレスをBASED項目に紐付けます。
これらは、可変長レコードの解析や、通信バッファの動的マッピングには欠かせませんが、コンパイラは「そのアドレスに本当に期待通りのデータが存在するか」を関知しません。
実装/解決策
動的なマッピングを行う際、最も重要なのは「ヘッダー情報による識別」です。単にポインタを切り替えるのではなく、対象データの先頭数バイトに「識別ID(レコードタイプ)」を持たせ、そのIDを判定した後にのみマッピングを行うガード節を設ける手法が有効です。これにより、意図しないアドレスへのマッピングによるメモリ破壊や誤った読み込みを防止できます。
サンプルプログラム
以下のコードは、可変長の通信データを識別子に基づいて安全にマッピングする例です。
IDENTIFICATION DIVISION.
PROGRAM-ID. DYNAMIC-STRUCT-SAMPLE.
WORKING-STORAGE SECTION.
- 受信バッファ(実際はもっと大きい)
01 RAW-BUFFER PIC X(100).
- マッピング用のBASED項目(ヘッダー部を共通化)
01 COMMON-HEADER BASED.
05 DATA-TYPE PIC X(01).
05 DATA-LEN PIC 9(04).
01 TYPE-A-DATA BASED.
05 FILLER PIC X(05).
05 VAL-A PIC 9(05).
01 TYPE-B-DATA BASED.
05 FILLER PIC X(05).
05 VAL-B PIC X(10).
PROCEDURE DIVISION.
- 1. バッファの先頭アドレスを取得
SET ADDRESS OF COMMON-HEADER TO ADDRESS OF RAW-BUFFER.
- 2. 型を判定してからマッピング(ここがガード節)
EVALUATE DATA-TYPE
WHEN ‘A’
SET ADDRESS OF TYPE-A-DATA TO ADDRESS OF RAW-BUFFER
DISPLAY “TYPE A: ” VAL-A
WHEN ‘B’
SET ADDRESS OF TYPE-B-DATA TO ADDRESS OF RAW-BUFFER
DISPLAY “TYPE B: ” VAL-B
WHEN OTHER
DISPLAY “不明なデータ型です。”
END-EVALUATE.
GOBACK.
応用・注意点
現場で最も多いバグは、「ポインタの付け替え忘れ」と「アライメントの不一致」です。
・NULLチェック: SET文でアドレスを割り当てる前に、ポインタがNULLでないかを確認する習慣をつけましょう。
・メモリ境界: 構造体をマッピングする際、ハードウェアのアライメント要件(特に4バイトや8バイト境界)を意識する必要があります。これを無視すると、特定の環境下で実行時エラーやパフォーマンス低下を招きます。
・デバッグの難しさ: BASED項目を使用したバグは、メモリダンプを追う必要があり、調査コストが非常に高くなります。マッピングの切り替え箇所には必ずログを仕込み、どのアドレスを参照しているかを可視化する設計を強く推奨します。

コメント