PL/I動的メモリ管理の深淵:FREE文と「消えない亡霊」への処方箋
メインフレームの現場で、S0C4(Protection Exception)のダンプを夜中に眺めることほど心臓に悪いことはない。特にPL/Iにおける動的メモリ操作は、現代のガベージコレクション付き言語に慣れた世代には、まさに「ナイフを裸で持ち歩く」ような危うい作業に見えるだろう。
しかし、基幹系バッチの処理量が増大し、固定長領域では対応しきれない複雑な構造体や、再帰的なデータ構造を扱う際、`ALLOCATE`と`FREE`は避けて通れない。今回は、PL/Iにおけるポインタ管理の真髄と、ダングリングポインタを回避するための「防壁」について解説する。
—
1. 悲劇の始まり:FREE文とダングリングポインタ
PL/Iにおいて`FREE`文を実行しても、ポインタ変数そのものは「解放されたアドレス」を保持し続ける。いわゆる「ダングリングポインタ(野良ポインタ)」の爆誕である。
/i
DCL P POINTER;
DCL 1 MY_REC BASED(P),
2 KEY CHAR(8),
2 VAL FIXED BIN(31);
ALLOCATE MY_REC;
/ …処理… /
FREE MY_REC;
/ ここで P はまだ割り当てられていたアドレスを指している /
P -> VAL = 999; / ここで地獄が始まる:S0C4またはデータ破壊 /
このコードの恐ろしいところは、環境によっては即座にABENDせず、「たまたま同じアドレスが再利用されるまでの間、しれっと書き込みが成功してしまう」ことだ。この「サイレント・データ・コラプション」こそが、マイグレーション時に我々を最も苦しめる。
実務上の鉄則:解放後の無効化
`FREE`の直後には、必ずポインタに`NULL()`を代入する。これをマクロやサブルーチンで徹底するチームと、個人の善意に頼るチームでは、3年後のシステム保守性に天と地ほどの差が生まれる。
/i
/ 安全なメモリ解放のためのラップを推奨 /
FREE MY_REC;
P = NULL(); / 解放済みポインタを無効化する儀式 /
—
2. コンパイラ最適化と「予期せぬ挙動」の罠
エンタープライズの現場では、コンパイラオプションの選択がプログラムの生死を分ける。特に`OPTIMIZE(3)`や`TEST`オプションの有無は、メモリ操作に敏感なコードでは致命的な差を生む。
- 最適化の影響: コンパイラは、`P`が変更されていないと判断すれば、メモリ上の値ではなくレジスタ値を信じて処理をショートカットする。`ALLOCATE`/`FREE`の順序が論理的に危うい場合、最適化レベルによって「ABENDしたり、しなかったり」という再現性の低い障害を引き起こす。
- パックデシマルの符号反転: 動的領域で構造体を操作する際、特にDB2からFETCHした`PIC S9(7) COMP-3`などのフィールドをポインタ経由で操作する場合、内部表現(X’F’やX’C’)が意図せず反転するケースがある。これは構造体のアライメントが正しくない(`ALIGNED`ではなく`UNALIGNED`がデフォルトになっている等)ことが原因の8割だ。
—
3. CICSおよびDB2環境でのエッジケース
CICSオンライン処理で`GETMAIN`の代わりに`ALLOCATE`を使う場合、注意すべきはタスク終了時のクリーンアップだ。PL/Iの`PROCEDURE`を抜ける際に解放し忘れたメモリは、タスク終了まで残る。
特にCICSの「疑似会話型(Pseudo-conversational)」処理では、ポインタを`STATIC`な領域(TWAなど)に退避させるような設計は厳禁だ。DB2の埋め込みSQLを使用する場合、`SQLDA`を動的メモリで確保するケースが多いが、ここでのポインタ管理ミスは、DB2のコントロールブロックを破壊し、システム全体を巻き込むABEND(S0C4またはS0CB)を誘発する。
—
4. マイグレーションに向けたアーキテクチャの視点
JavaやC#への移行を検討しているテックリードに忠告したい。PL/Iの「ポインタによるダイレクトなメモリ操作」を、そのままオブジェクト指向言語の参照型に置き換えてはいけない。
1. カプセル化: ポインタを直接操作するロジックは、徹底して専用の「アクセサ・メソッド(またはクラス)」に閉じ込めること。
2. ダンプ解析の文化: 現代のデバッガに頼り切るのではなく、`CEEDUMP`を読み解き、ストレージ・ダンプから「このアドレスはどの変数の領域か」を逆算できる能力を、次世代のメンバーに継承しなければならない。
3. セーフティ・ネットの構築: マイグレーション前段階として、既存のPL/Iコードに「メモリ解放チェック用」のデバッグコードを一時的に埋め込み、ダングリングポインタの発生箇所を特定するプロファイリングを行うべきだ。
結びとして
メインフレームのPL/Iは、極めて強力な言語だ。しかし、その力は「コードが何をしようとしているか」をプログラマが完璧に把握していることが前提となっている。`FREE`を実行するその瞬間、自分が何を殺そうとしているのか、そしてその亡霊がどこに潜んでいるのかを常に意識すること。
それが、レガシーを次世代へ安全にバトンタッチするための、唯一の道である。
