【実務・中級編】STATIC属性と自動ストレージ(AUTOMATIC)の生存期間 – PL/Iの基本構文とデータ制御実践ガイド

メインフレームの闇を照らす:STATIC変数とAUTOMATIC変数の「生存期間」を正しく理解する

現場の若手エンジニアから、たまにこんな質問を受ける。「なぜこの変数は、サブルーチンを抜けても値が残っているのか?」「なぜこのポインタは、次の呼び出しで予期せぬアドレスを指しているのか?」と。

大規模バッチの改修やマイグレーションの現場では、コンパイラの仕様を「なんとなく」で使っていると、必ずと言っていいほど不可解なバグに足元をすくわれる。今日は、PL/Iのメモリ管理の根幹である「生存期間(Storage Duration)」、特にSTATICとAUTOMATICの違いについて、現場の視点から深掘りしていこう。

1. 記憶域クラスの基本:STATIC vs AUTOMATIC

PL/Iにおいて、変数の宣言時に指定する記憶域クラスは、単なる「型」以上の意味を持つ。それは、その変数が「いつ生まれ、いつ消えるか」という寿命を決定する。

  • AUTOMATIC(デフォルト): ブロック(PROCEDUREやBEGIN)に入った瞬間にメモリが確保され、ブロックを抜けると容赦なく破棄される。いわゆる「スタック」上のデータだ。
  • STATIC: プログラムのロード時にメモリが確保され、プログラムの終了までその領域は固定される。まさに「基幹システムの番人」だ。

なぜこれが「バグの温床」になるのか?

現場でよく見る悲劇は、「再入可能(Reentrant)であるべきモジュールで、安易にSTATIC変数を使ってしまう」パターンだ。特に、CICSやマルチスレッド環境に近い制御フローを持つプログラムでこれをやると、前のトランザクションのゴミが次の処理に引き継がれ、原因不明の誤計算を引き起こす。

2. 実践的なコードで見るメモリ配置の挙動

以下のコードを見てほしい。VSAMファイルへのアクセスと、STATIC変数を活用した「呼び出し回数のカウント」を実装した例だ。

1
/ PROGRAM: SAMPLE01 – STATICとAUTOMATICの挙動デモ /
TEST_PROC: PROCEDURE OPTIONS(MAIN);

/ STATICはロード時に一度だけ初期化される /
DCL CALL_COUNT FIXED BIN(31) STATIC INIT(0);

/ AUTOMATICはPROCEDUREが呼ばれるたびに再構築される /
DCL WORK_AREA CHAR(80) AUTOMATIC;

/ 処理開始 /
CALL_COUNT = CALL_COUNT + 1;
PUT SKIP LIST(‘今回の呼び出し回数:’, CALL_COUNT);

/ 内部サブプロシージャ呼び出し /
CALL SUB_PROCESS;

/ 終了処理 /
RETURN;

SUB_PROCESS: PROCEDURE;
/ この変数はここを抜けると消滅する /
DCL LOCAL_BUFFER CHAR(10) AUTOMATIC INIT(‘DATA_VAL’);

PUT SKIP LIST(‘内部処理中:’, LOCAL_BUFFER);
END SUB_PROCESS;

END TEST_PROC;

ここが技術のポイント

  • 初期化のタイミング: `STATIC`変数の`INIT`値は、プログラムがロードされた瞬間に一度だけ設定される。`CALL`されるたびに0に戻ることはない。
  • スタック領域の節約: 大きな配列(`DCL BIG_ARRAY(10000) CHAR(100)`など)を`AUTOMATIC`で宣言すると、プログラム開始時にスタックが溢れる可能性がある。大規模データは`STATIC`、あるいは`CONTROLLED`(必要に応じて自分で確保・解放)を用いるのが賢い設計だ。

3. トラブルシューティングの現場から:ONユニットとの付き合い方

`ON`ユニット(例外処理)を書く際にも、この「寿命」は重要だ。`ON`ユニット内で`AUTOMATIC`変数を参照しようとすると、その変数が宣言されたブロックが既に終了していれば、参照先は不正なメモリ領域(ダングリング・ポインタに近い状態)になる。

1
/ ファイル読み込みの例外処理 /
ON ENDFILE(VSAM_FILE) BEGIN;
/ ここでAUTOMATIC変数を参照してはいけない! /
/ 既に制御が戻っている可能性があるため /
PUT SKIP LIST(‘ファイル終了しました’);
END;

もし、`ON`ユニットで状態を保持したい場合は、必ず`STATIC`、あるいは外部から渡された引数(ポインタ)を経由して安全を確保する必要がある。

4. ベテランからのアドバイス:保守性を高めるために

1. デフォルトを信じるな: `AUTOMATIC`が暗黙的であることは知っておくべきだが、コードレビューでは明示的に`DCL VAR AUTOMATIC`と書く文化があっても良い。意図が明確になるからだ。
2. デバッグのコツ: 「値がなぜか変わっている」という現象に遭遇したら、まずはその変数が`STATIC`かどうかを確認せよ。複数個所で更新されている可能性が極めて高い。
3. BUILTIN関数の活用: `ADDR(変数)`を使って、変数がスタック上にあるのか(アドレス値が特定範囲内)、それとも静的領域にあるのかをダンプ出力で追う技術は、メインフレームエンジニアの最後の砦だ。

PL/Iは古いが、そのメモリ管理モデルは極めて論理的だ。STATICとAUTOMATICの境界を意識することは、単にバグを防ぐだけでなく、コンピュータのメモリ構造を理解するということと同義である。

今日のコード改修も、この視点を持って臨んでみてほしい。きっと今まで見えなかった「メモリの息遣い」が聞こえてくるはずだ。

タイトルとURLをコピーしました