【PL/I学習|実務向け】メインフレーム技術者のためのPL/I:STATIC変数の「INITIAL」制約と物理メモリの仕組み

1. 導入:なぜSTATIC変数の初期化に制限があるのか

メインフレームのPL/I開発において、STATIC属性を持つ変数は、プログラムの実行開始時に一度だけ初期化されます。しかし、この初期化式には「定数または定数式」しか記述できないという厳格なルールがあります。なぜ `TIME()` のような実行時の関数結果が使えないのか。それは、この初期化が「ロード時に物理的なメモリコピーで行われる」という、メインフレーム特有のアーキテクチャ上の制約があるためです。この仕組みを理解していないと、コンパイルエラーに悩まされるだけでなく、意図しないメモリ破壊を引き起こすリスクがあります。

2. 基礎知識:PL/IのSTATICとロードモジュールの関係

PL/IのSTATIC変数は、プログラムがメモリにロードされた時点で、その値がロードモジュール(実行形式)の中に「バイナリイメージ」として既に埋め込まれています。Javaの `static` 初期化ブロックのように、実行時に複雑なロジックを走らせて値を確定させるのではなく、プログラムという「静的な塊」の中に、あらかじめ初期値という「データ」が焼き付けられているイメージです。そのため、ロード時に値を確定できない動的な値(関数呼び出し等)を記述すると、コンパイラは「ロード時に確定できない値である」としてエラーを返します。

3. 実装/解決策:動的値の初期化はどうすべきか

コンパイル時に確定できない値を初期化したい場合は、STATICでの初期化を諦め、実行時の「PROCEDUREの開始時」に代入を行うのが正攻法です。あるいは、フラグ変数を用いて「初回アクセス時のみ初期化する」というロジックを組み込みます。

4. サンプルプログラム:STATICの制限と回避策の比較

以下のコードは、コンパイルエラーになる例と、実務でよく使われる回避パターンです。

/ NG: コンパイルエラーになる例 /
/ DCL CURRENT_TIME CHAR(8) STATIC INIT(TIME()); /

/ OK: 実務で推奨される手法 /
DCL INIT_FLAG BIT(1) STATIC INIT('0'B);
DCL WORK_TIME CHAR(8) STATIC;

PROCEDURE_NAME: PROC;
    / 初回のみ実行する初期化ロジック /
    IF ^INIT_FLAG THEN DO;
        WORK_TIME = TIME(); / ここで実行時に値をセット /
        INIT_FLAG = '1'B;
    END;

    / 以降、WORK_TIMEを定数的に利用する /
END PROCEDURE_NAME;

5. 応用・注意点:現場で陥りやすい罠

実務で特に注意すべきは、マルチスレッド環境や再入可能(REENTRANT)なプログラムにおけるSTATIC変数の扱いです。STATIC変数はプログラムのロードモジュールに紐付くため、複数のタスクから同時に同じプログラムが呼び出された場合、STATIC変数はすべてのタスクで共有されます。

もし「タスクごとに異なる初期値を持ちたい」という要件であれば、STATICではなくAUTOMATIC変数を使用し、プログラムの入り口で初期化処理を行うべきです。また、コンパイルエラーを回避するために安易にSTATICを多用すると、メモリ使用量が増加し、ロードモジュールのサイズが肥大化する原因にもなります。メインフレームの限られたリソースを最適化するためにも、初期化のタイミングと変数の有効範囲を適切に設計することが、熟練技術者への第一歩です。

コメント

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