【PL/I学習|実務向け】PL/IにおけるBASED変数とREFER句の罠:長さ再確定の正しい理解

1. 導入:なぜREFERの挙動を理解すべきか

メインフレーム開発の現場でPL/Iを使用する際、可変長データを扱うために「REFER句」は非常に便利です。しかし、REFER句を持つBASED変数は、現代のJavaやC#のListのような「動的拡張」とは根本的に仕組みが異なります。多くの開発者が「REFER値 N を書き換えれば配列サイズも変わる」と誤解し、結果としてメモリ破壊(Buffer Overflow)を引き起こすケースが後を絶ちません。今回は、安全かつ正確にREFERを制御するための設計指針を解説します。

2. 基礎知識:REFER句の仕組み

REFER句は、構造体内の変数の値を参照して、動的メモリ(BASED変数)の実際のサイズを定義する仕組みです。
重要な点は「サイズが確定するのはALLOCATE時、またはREAD時である」という点です。メモリは一度確保されると、その領域内でのREFER値の変更は、単なる「変数への代入」に過ぎず、物理的なメモリ領域の伸縮は一切行われません。これを理解せずに配列のインデックスを操作すると、確保した領域外へアクセスする重大な障害に繋がります。

3. 実装と解決策:長さの再確定手順

REFER値を変えて領域を再利用したい場合は、以下の手順が鉄則です。
1. 現在のポインタをFREEする。
2. 新しいサイズ(REFER値)をセットする。
3. 改めてALLOCATEを行う。
単に値を書き換えて使い回すのは避け、必ず「再確保」のサイクルを回してください。

4. サンプルプログラム:安全な再確保の実装例

以下は、BASED変数を適切に再確保するサンプルです。

/ 構造体の定義 /
DCL 1 TABLE_STRUCT BASED(P_TABLE),
2 TABLE_LEN FIXED BIN(31),
2 TABLE_DATA(1 REFER(TABLE_LEN)) CHAR(8);

DCL P_TABLE POINTER;
DCL NEW_SIZE FIXED BIN(31) INIT(10);

/ 1. 初回の確保 /
TABLE_LEN = 5;
ALLOCATE TABLE_STRUCT;

/ 2. サイズを変更して再利用する場合の正しい手順 /
FREE TABLE_STRUCT; / 一度解放する /
TABLE_LEN = NEW_SIZE; / 新しい長さをセット /
ALLOCATE TABLE_STRUCT; / 再確保によりメモリ領域が確定 /

/ これで TABLE_DATA(10) まで安全にアクセス可能 /
TABLE_DATA(10) = ‘COMPLETE’;

5. 応用・注意点:現場でのバグ回避

現場で陥りやすいのが「ポインタの付け替え忘れ」や「FREE漏れ」です。特に以下の点に注意してください。

・ポインタの再初期化:
FREEをした後、ポインタ変数が旧アドレスを指したままにならないよう注意してください。意図しないゴミメモリへのアクセスを招きます。

・REFER値と物理長の乖離:
構造体を受け渡す際、呼び出し側と受け取り側でREFER値(制御フィールド)の整合性が取れていないと、システム異常終了(ABEND)となります。特に外部プログラムやファイルから読み込む際は、必ず定義値のチェックを行ってください。

・現代言語との比較:
「サイズを変える=自動拡張」と考えると痛い目を見ます。PL/Iのメモリ管理はあくまで「明示的な割り当てと解放」が原則です。メモリの安全性は開発者の手元にあることを常に意識してください。

コメント

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