現場のエンジニアへ告ぐ:PL/IのCONTROLLED属性を「なんとなく」使うな
メインフレームの現場で何十年も生き残っているPL/Iだが、その柔軟性が災いしてか、今なお「メモリリーク」や「意図しないデータ破壊」の温床となっている箇所がある。特に`CONTROLLED`属性は、使いこなせば強力な武器になるが、スタック管理の仕組みを理解せずに書けば、バッチが深夜の運用で突然異常終了(ABEND)する原因になりかねない。
今日は、CONTROLLEDストレージのスタック構造と、実務で絶対に守るべき鉄則を共有しよう。
—
CONTROLLED属性の本質:スタック管理の正体
通常、PL/Iの変数は`AUTOMATIC`(自動スタック)として確保されるが、`CONTROLLED`を指定すると、プログラマがメモリの寿命を完全に制御できる。
ここで重要なのは、`ALLOCATE`を実行するたびに、その変数は「スタックの頂上」に積み上げられるということだ。既存の同名変数は隠蔽され、`FREE`を実行すると、現在スタックの頂上にあるものが破棄され、その下の層(一つ前の世代)が再び有効になる。
この挙動を「世代管理」として活用できるかどうかが、ベテランと初心者の分かれ目だ。
—
実践的コード例:動的配列のスタック管理
以下の例は、VSAMファイルから読み取ったレコードを、可変長のスタック構造で処理する際の定石だ。
1
TEST_STACK: PROCEDURE OPTIONS(MAIN);
/ CONTROLLED属性で宣言された構造体 /
DCL 1 WORK_REC CONTROLLED,
2 KEY_ID CHAR(8),
2 DATA_VAL FIXED BIN(31);
/ VSAMファイル定義(簡略化) /
DCL VSAM_FILE FILE RECORD INPUT;
/ エラーハンドリング:ONユニットの制御フロー /
ON ENDFILE(VSAM_FILE) BEGIN;
/ スタックが空になるまで解放する安全なループ /
DO WHILE(ALLOCATION(WORK_REC) > 0);
FREE WORK_REC;
END;
STOP;
END;
OPEN FILE(VSAM_FILE);
DO FOREVER;
/ スタックに新しい世代を追加 /
ALLOCATE WORK_REC;
READ FILE(VSAM_FILE) INTO(WORK_REC);
/
- ここでALLOCATIONビルトイン関数を使い、
- 現在のスタック深さをチェックするのはデバッグの基本だ
/
PUT SKIP LIST(‘現在のスタック深度:’ || ALLOCATION(WORK_REC));
/
- 処理ロジック…
- もしここでFREEを忘れると、ループのたびに領域が確保され、
- いずれGETMAINエラーでシステムごと落とすことになる
/
FREE WORK_REC;
END;
END TEST_STACK;
—
現場で陥る「スタック・トラップ」の回避策
実務において、`CONTROLLED`を扱う際に必ず覚えておくべきポイントは以下の3点だ。
1. ALLOCATIONビルトイン関数の活用
「今、何層積み上がっているか?」を把握することは、バグ調査の第一歩だ。`ALLOCATION(変数名)`は、現在のスタックの深さを返してくれる。`FREE`をしたはずなのにメモリエラーが出る場合、まずはログにこの値を吐き出して、意図せぬネストが発生していないか確認しろ。
2. FREEの確実な実行
例外処理(ONユニット)の中に`FREE`を書くのは非常に重要だが、もっと良いのは「構造化」だ。可能な限り`ALLOCATE`と`FREE`を同一プロシージャ内のスコープに収めろ。呼び出し先で`ALLOCATE`し、戻り側で`FREE`するような設計は、メンテナンスの難易度を跳ね上げるだけだ。
3. 世代管理とポインタの意識
`CONTROLLED`変数は、内部的にはポインタのチェインで管理されている。誤って同じポインタを二重に操作したり、解放済みの世代を参照したりするコードは、メインフレーム特有の「データの一貫性欠如(サイレントデータ破損)」を引き起こす。これが一番恐ろしい。デバッグ時は、必ずコンパイラオプションで適切なストレージ保護(`CHECK`や`SUBSCRIPTRANGE`など)を有効にしてテストを行え。
—
最後に:スペシャリストへの道
PL/Iの強みは、開発者がハードウェアの限界に近い領域まで直接制御できることにある。`CONTROLLED`属性によるスタック管理は、現代の言語にはない、メインフレームエンジニアだけの特権だ。
「とりあえず動けばいい」ではなく、「メモリの世代が今どこにあるか」を頭の中で可視化できる人間になれ。そうすれば、複雑なバッチ改修でも、誰よりも早く問題の核心に辿り着けるはずだ。
もし大規模マイグレーションで古いコードの解析に詰まったら、まずは`ALLOCATE`の回数と`FREE`のペアが正確か、ログを辿ることから始めることだ。それが、トラブルシュートの近道だ。健闘を祈る。
