メインフレームの守護者へ贈る:PL/I動的メモリ確保と「STORAGE」条件の深淵
夜中のバッチジョブが異常終了し、オペレーターからのアラートで叩き起こされる。そんな時、ログの最後に見つけるのが `IGZ0000I` や、PL/I特有の「STORAGE」条件による突然の死です。
「メモリは十分に積んでいるはずなのに、なぜここで落ちるのか?」
大規模な基幹システムにおいて、動的メモリ(ヒープ領域)の枯渇は、単なるプログラミングのミスではなく、設計思想そのものを問われる事象です。今日は、PL/Iの `ALLOCATE` 文と、それに伴う例外ハンドリングの真髄について、現場の知見を交えて解説します。
—
1. なぜ「STORAGE」条件が発生するのか
PL/Iにおいて `ALLOCATE` 文を用いたメモリ確保は、プログラマに強力な裁量権を与える反面、システムリソースに対する責任も負わせます。`STORAGE` 条件は、ランタイムが要求されたサイズのストレージを確保できないと判断した瞬間に発生します。
原因は大きく分けて3つです。
- メモリリーク: `FREE` し忘れたポインタの山。
- 断片化 (Fragmentation): 小さな確保と解放を繰り返した結果、大きな連続領域が確保できなくなる現象。
- 上限設定の限界: LE (Language Environment) のヒープ設定(`HEAP` ランタイムオプション)が、業務の最大負荷に耐えきれていない。
これらに直面したとき、デバッグの海で溺れないための「備え」が `ON STORAGE` ユニットです。
—
2. 実践:安全な動的メモリ確保のテンプレート
現場で保守を行う際、私は必ず以下のパターンで実装するように指導しています。ただ `ALLOCATE` するのではなく、障害発生時の「状況保存」と「安全な終了」をセットにするのがプロの流儀です。
1
/ —————————————————————— /
/ DYNAMIC_ALLOC_SAMPLE: 安全なメモリ確保のデモンストレーション /
/ —————————————————————— /
TEST_PROG: PROCEDURE OPTIONS(MAIN);
/ 構造体定義:動的に確保するデータのテンプレート /
DCL 1 DATA_AREA BASED(P_AREA),
2 REC_ID CHAR(8),
2 REC_DATA CHAR(4000);
DCL P_AREA POINTER;
DCL IS_ERROR BIT(1) INIT(‘0’B);
/ STORAGE条件発生時のハンドリングを定義 /
ON STORAGE
BEGIN;
PUT SKIP LIST(‘!!! STORAGE ERROR OCCURRED !!!’);
PUT SKIP LIST(‘メモリ確保に失敗しました。現在の状況をダンプします。’);
IS_ERROR = ‘1’B;
/ ここで必要に応じてクリーンアップ処理を呼び出す /
END;
/ メモリ確保処理 /
ALLOCATE DATA_AREA;
/ エラーフラグを確認 /
IF IS_ERROR THEN DO;
CALL ABEND_ROUTINE; / システム固有の異常終了処理 /
END;
/ 正常時の処理 /
P_AREA->REC_ID = ‘BATCH001’;
/
- VSAMアクセスやレコード処理が続く場合は、
- 終了時に必ずFREEすることを忘れないこと。
- これを怠ると、長期間稼働するバッチで必ず再発する。
/
FREE DATA_AREA;
END TEST_PROG;
—
3. 現場のエンジニアが知っておくべき「コツ」
① LEランタイムオプションの再確認
コードが正しくても、JCL側の `CEEOPTS` で指定している `HEAP` 設定が `ANYWHERE` になっていない、あるいは初期値が小さすぎるケースが多々あります。
- `HEAP(,,ANYWHERE)` を指定し、31ビットアドレッシングを活用できているか確認してください。
② `ALLOCATE` 前のポインタ初期化
ポインタ変数(`P_AREA` など)が初期化されていない状態で `FREE` を実行したり、誤ったアドレスを参照したりすれば、即座に `S0C4`(保護例外)の餌食です。定義時に `INIT(NULL())` を付加する習慣をつけましょう。
③ BUILTIN関数の活用
`ADDR` や `NULL` といったビルトイン関数は、単なるユーティリティではありません。デバッグ時に `DISPLAY` 文でアドレス値を追跡することで、「今、自分がメモリのどの領域を触っているのか」を可視化できます。
—
結びに代えて
PL/Iは古臭い言語だと言われることもありますが、システム資源を緻密に制御できるその設計は、現代のメモリ管理の原点です。`ON STORAGE` ユニットを適切に配置することは、いわば「転ばぬ先の杖」。
バッチ処理において、メモリ不足で落ちるか、それともエラーハンドリングで適切にログを残して次回の再開を容易にするか。その差が、運用担当者からの信頼に直結します。
また、複雑なバッチ改修で迷ったときは、マニュアルの行間を読み解く前に、まずはメモリのライフサイクルを紙に書いて整理してみてください。それが、大規模メインフレームシステムの深淵を覗き、かつ生還するための最短ルートです。
次回のブログでは、「VSAM入出力におけるバッファ管理とポインタの最適化」について掘り下げていこうと思います。それでは、良いバッチ運用を。
