PL/Iの「CONTROLLED」が切り開く動的メモリ管理の深淵:スタック構造と再帰の罠
長年、汎用機の暗いデータセンターの片隅で、数百万行のPL/Iソースと格闘してきたエンジニアにとって、`CONTROLLED`属性は「諸刃の剣」である。JavaのガベージコレクションやC#のマネージドメモリに慣れ親しんだ若手アーキテクトには、この明示的なスタック管理こそが、レガシーシステムの「神の視点」を支える基盤であると力説したい。
今日は、単なる文法解説ではない。スタックの深層で何が起きているのか、そしてマイグレーション時に我々がなぜ頭を抱えることになるのか、その核心に触れる。
—
1. CONTROLLED属性の本質:スタックの階層管理
`CONTROLLED`変数は、単なる動的確保ではない。`ALLOCATE`と`FREE`によって、その変数は「スタック状」に積み上がる。ここが最大のポイントだ。再帰呼び出しの中で`ALLOCATE`を繰り返すと、新しいインスタンスが旧インスタンスの上にプッシュされ、直近のインスタンスのみがアクティブになる。
/i
/ CONTROLLED変数のスタック挙動を確認するサンプル /
DCL MY_BUFFER CHAR(100) CONTROLLED;
PROC_RECURSIVE: PROC(DEPTH) RECURSIVE;
DCL DEPTH FIXED BIN(15);
ALLOCATE MY_BUFFER; / 新しい世代をプッシュ /
MY_BUFFER = ‘DEPTH:’ || TRIM(CHAR(DEPTH));
IF DEPTH > 0 THEN
CALL PROC_RECURSIVE(DEPTH – 1);
PUT SKIP LIST(MY_BUFFER); / ここでは常に最新のALLOCATEが参照される /
FREE MY_BUFFER; / スタックからポップし、一つ前の世代が復元される /
END PROC_RECURSIVE;
この「LIFO(後入れ先出し)」構造を理解せず、`FREE`を忘れるとどうなるか。当然ながらストレージリークだ。しかし、もっと恐ろしいのは、マイグレーション先で「なぜか値が化ける」という現象である。C++のRAII(Resource Acquisition Is Initialization)とは異なり、PL/Iの`FREE`を忘れてもコンパイラは何も言わない。ランタイムの深淵で、メモリは静かに腐敗していく。
—
2. ポインタとベース変数による「禁断の操作」
`CONTROLLED`変数を、`BASED`変数やポインタ演算と組み合わせると、システムアーキテクトの腕の見せ所となる。特にDB2のフェッチループやCICSの通信領域(COMMAREA)の解析において、動的にサイズが変わる構造体を扱う際、`ADDR()`と`OFFSET`を駆使したメモリ操作は不可欠だ。
しかし、ここで忘れてはならないのが、パックデシマル(FIXED DECIMAL)の内部表現だ。
- 罠の正体: `CONTROLLED`領域に直接ポインタでアクセスし、構造体をオーバーレイする際、パックデシマルの符号ビット(F, C, D)が反転、あるいは不正な値になっているケースがある。
- 対策: `CHECK`オプションを有効にしたコンパイルでアベンドさせ、ダンプを採取せよ。特に`S0C7`(データ例外)が発生した場合、それは計算エラーではなく、メモリ上の「ゴミ」を整数として評価した瞬間に発生する。
—
3. マイグレーションにおける最大の障壁:スタックの共有とDB2
もし君が今、このPL/IコードをJavaやC#へマイグレーションしようとしているなら、以下のエッジケースを設計書に書き加えることを強く推奨する。
1. 再帰とスレッドセーフ: PL/Iの`CONTROLLED`スタックはプロセス(タスク)ごとに管理されるが、Javaのスタックはスレッドごとだ。再帰の深さが、Java側の`StackOverflowError`の閾値に達しないか、必ず検証が必要だ。
2. CICSオンラインとの親和性: CICS環境下では、`GETMAIN`によって確保される領域と`CONTROLLED`変数の生存期間が異なることがある。`FREE`を忘れたままタスクが終了すると、そのメモリは再利用されず、CICSのショートオンストレージ(SOS)を招く。マイグレーション後のメモリ管理モデルが、この「タスク終了時のクリーンアップ」を自動保証しているか、再確認が必要だ。
—
4. 最後に:アーキテクトへの提言
`CONTROLLED`変数は、現代の言語からは排除されつつある概念だが、その背後にある「メモリをいつ確保し、いつ解放するか」という極めて原始的かつ重要な哲学は、どれだけ技術が進化しても変わらない。
アベンドが発生したとき、`CEE3DMP`(Language Environmentのダンプ)を恐れるな。それはシステムが君に語りかけている「真実」の記録だ。スタックポインタがどこを指し、`CONTROLLED`の世代管理がどこで破綻したのか。その軌跡を辿ることは、システムという巨大な生命体の鼓動を聴くことに他ならない。
レガシー移行は、単なるコードの書き換えではない。過去の設計思想を理解し、それを現代の安全な枠組みへと「昇華」させる儀式である。君が手掛けるそのシステムが、今後数十年の安定稼働を約束する礎となることを期待している。
