PL/Iの「可変長構造体」を攻略せよ!REFERオプションでメモリを自由自在に操る
こんにちは。メインフレームの世界へようこそ。
Javaで`ArrayList`を使い、COBOLで`OCCURS DEPENDING ON`を書いてきた皆さんにとって、PL/Iのメモリ管理は少しだけ「古典的」で、そして非常にパワフルに映るはずです。
今日は、PL/Iプログラミングにおける一つの山場であり、同時に醍醐味でもある「BASED変数とREFERオプション」について紐解いていきましょう。これさえ理解すれば、可変長データの扱いで頭を抱えることはなくなりますよ。
—
そもそも「BASED変数」って何?
Javaなどの言語では、メモリの確保はランタイム(ガベージコレクタ)に任せっきりですよね。しかし、PL/Iは「メモリの番人」として、プログラムが自ら必要な分だけを確保するスタイルをとります。
`BASED`という属性は、「ここにはデータの実体はないけれど、この構造でメモリを解釈してね」というテンプレートのようなものです。ポインタを使って、メモリ上の特定の場所を指し示すための「型定義」だと考えてください。
REFERオプション:可変長構造体の「賢い」サイズ指定
データベースから読み込むデータや、通信電文には「データの長さが都度変わる」ものがよくありますよね。例えば、「社員情報」のあとに「保有資格リスト」が続くようなデータ構造です。
ここで登場するのが`REFER`オプションです。
基本的なコード例を見てみよう
まずは、このコードを見てください。
1
/ 可変長構造体の定義 /
DECLARE 1 EMPLOYEE_REC BASED(P_EMP),
2 EMP_ID FIXED BIN(31),
2 QUAL_COUNT FIXED BIN(15), / これが長さの基準 /
2 QUAL_LIST(1 REFER(QUAL_COUNT)) / REFERで動的にサイズ決定 /
CHAR(10);
この宣言、とても面白いですよね。
`QUAL_LIST`という配列のサイズを、同じ構造体の中にある`QUAL_COUNT`という変数が「動的に見ている」わけです。
- QUAL_COUNT: 今、資格がいくつあるか(例:3つ)
- REFER(QUAL_COUNT): 「QUAL_COUNTの値を見て、配列のサイズをその数に合わせるよ!」という宣言
このように書くことで、プログラムが実行時に`QUAL_COUNT`の値をセットし、必要十分なメモリだけを割り当てることができるのです。
—
注意点:メモリレイアウトの「深淵」
さて、ここからが現場の知見です。PL/Iでこの構造体を使う際、必ず頭に入れておいてほしい注意点が2つあります。
1. メモリの「確保」を忘れない
`BASED`変数はあくまでテンプレートです。メモリ上に領域を確保するには、明示的に`ALLOCATE`文を発行する必要があります。
1
/ 資格数が3つの場合 /
QUAL_COUNT = 3;
ALLOCATE EMPLOYEE_REC;
/ これにより、メモリ上に「ID + カウント + 3つ分の資格領域」が確保される /
`ALLOCATE`を行わずに`P_EMP`(ポインタ)を使おうとすると、即座に「S0C4(メモリ保護例外)」でプログラムが異常終了します。メインフレームの洗礼ですね。怖いですか? 大丈夫、`ALLOCATE`の儀式を忘れなければ何も起きません。
2. コンパイラは「ここ」を見ている
`REFER`が参照している変数は、構造体の先頭付近に配置するのが鉄則です。コンパイラは構造体のレイアウトを計算する際、`REFER`変数からその直後の配列のオフセットを算出します。
構造体を複雑にネストさせすぎると、この計算が追いつかず、期待したオフセットからデータがずれるという「バグの温床」になりかねません。
—
まとめ:怖がらずに、まず書いてみよう
PL/Iの`REFER`オプションは、一見すると古臭い記法に見えるかもしれません。しかし、これは「限られたメモリリソースを極限まで効率的に使う」ための、先人たちの知恵の結晶です。
- BASED変数は「型(テンプレート)」として定義する。
- REFERは、配列サイズを動的に制御する「参照先」を指定する。
- ALLOCATEでメモリを確保するまでがワンセット。
この3つをセットで覚えておけば、どんな複雑な可変長レコードも怖くありません。
もし実務でコードを追いかけていて、「あれ、ここのポインタどこを指してるの?」と迷子になったら、一度落ち着いて`ALLOCATE`の行を探してみてください。きっと、データ構造の全貌が見えてくるはずですよ。
それでは、次回のメインフレーム・アーキテクチャ講座でお会いしましょう!
