メインフレームの闇、「野良ポインタ」を狩る:PL/IにおけるFREE文とメモリ管理の鉄則
現場の皆さん、お疲れ様です。今日も今日とて、夜間バッチのS0C4(アドレッシング例外)と格闘していませんか?
PL/Iの歴史は長い。我々が扱っているのは、かつての偉大な先人たちが積み上げた堅牢な基幹システムですが、その柔軟性が災いして、現代のエンジニアを悩ませる「メモリ管理」という魔物が潜んでいます。特に、動的メモリ(BASED変数)を操作する際、`FREE`文を打った後の「ダングリングポインタ(解放済み領域を指すポインタ)」の扱いは、デバッグの最難関の一つです。
今日は、大規模バッチ改修で「なぜか本番環境でだけ落ちる」という悪夢を避けるための、現場の実践的な設計指針を伝授しましょう。
—
なぜ、FREEした後に「NULL」を代入しなければならないのか
`FREE`文は、動的に割り当てたメモリをシステムに返却するだけの命令です。しかし、驚くべきことにPL/Iのポインタ変数は、`FREE`の後も前のメモリ番地を指したままです。
もし、そのポインタをそのままにしておいて、誤って参照しようものなら……。幸運なら即座にS0C4で異常終了しますが、不運な場合はそのメモリ領域が別の処理で再利用され、「データが化ける」という最も厄介な事象を引き起こします。
これを防ぐ唯一の防御策は、`FREE`の直後にポインタを `NULL()` に戻すこと。これに尽きます。
実践:安全な動的メモリ管理のコーディング標準
以下に、VSAMファイルから可変長レコードを読み込み、メモリ上で処理して解放する、現場でそのまま使えるテンプレートを示します。
1
/ —————————————————————— /
/ メモリ管理を意識した動的処理のサンプルコード /
/ —————————————————————— /
DEMO_PROC: PACKAGE;
DCL PTR_REC PTR INIT(NULL()); / 必ず初期値NULLで宣言すること /
DCL 1 REC_STR BASED(PTR_REC), / 動的領域の定義 /
5 KEY_FLD CHAR(10),
5 DATA_FLD CHAR(100);
/ 処理メインブロック /
PROCESS_LOGIC: PROC OPTIONS(MAIN);
/ 1. 動的メモリの確保 /
ALLOCATE REC_STR;
/ 2. VSAM等の読み込み処理(イメージ) /
/ READ FILE(VSAM_FILE) INTO(REC_STR); /
/ 3. 安全なデータ処理 /
IF PTR_REC ^= NULL() THEN DO;
PUT SKIP LIST(‘DATA:’, REC_STR.DATA_FLD);
END;
/ 4. メモリ解放とダングリングポインタの無効化 /
FREE REC_STR;
PTR_REC = NULL(); / 【重要】ここを忘れると後でS0C4の温床になる /
END PROCESS_LOGIC;
END DEMO_PROC;
ONユニットとの組み合わせによる「二重の備え」
バッチ処理において、`ALLOCATE`の失敗やポインタ不正を検知するために、`ON`ユニットを活用するのは基本中の基本です。
1
/ メモリ領域不足やアドレス例外に対する監視 /
ON STORAGE BEGIN;
PUT SKIP LIST(‘メモリ領域が枯渇しました’);
CALL DUMP_AND_EXIT; / 独自のダンプ出力・終了ルーチンへ /
END;
ON CONDITION(ERROR_PTR) BEGIN;
/ ここでポインタの状態をチェックするロジックを組む /
END;
実務で生き残るための教訓
1. ポインタの初期値は常にNULL: `DCL PTR_A PTR INIT(NULL());` を省略してはいけません。未定義のポインタは、ゴミデータが残っている可能性があり、最初から「地雷」を抱えて走ることになります。
2. FREEとNULL代入は「対(つい)」: コーディング規約で「`FREE`文の次の行には必ず`NULL()`代入」と明記させましょう。コードレビューでここを指摘できないのは、コードを読んでいないのと同じです。
3. ADDPARMによるデバッグ: もしS0C4が頻発するなら、`PLIDUMP`を呼び出すONユニットを仕込み、ダンプを採取してください。問題のポインタが指しているアドレスが、最後に`FREE`したアドレスと一致しているか確認すれば、原因は一発で特定できます。
PL/Iは、書き手の手腕がそのままシステムの安定性に直結する、ある意味で非常に正直な言語です。メモリ管理を制する者は、メインフレームのバッチ処理を制します。
皆さんのコーディングが、深夜の呼び出しに繋がらない堅牢なものになることを願っています。何か不明点があれば、またいつでも聞いてください。それでは、実装頑張りましょう。
