【実務・中級編】INITIAL属性による変数の初期化 – PL/Iの基本構文とデータ制御実践ガイド

【PL/I深層解説】INITIAL属性の罠:なぜその変数は、次の呼び出しで「そのまま」なのか?

若手からベテランまで、メインフレームのPL/Iコードを触っていて一度は頭を抱えるのが「変数の初期化」のタイミングだ。特に`INITIAL`属性を使っている時、うっかり「プロシージャを呼ぶたびに初期値が入るはず」と思い込んでバグを生むケースは後を絶たない。

今日は、IBMメインフレームの現場で何十年も生き残ってきたPL/Iの「初期化の作法」について、実務の視点から深掘りしてみよう。

1. 予約語なき自由と、それが招く「初期化」の誤解

まず前提として、PL/IにはC言語のような絶対的な「予約語」が存在しない。`IF`も`THEN`も、変数名として使えてしまう。この柔軟性は強力だが、裏を返せば「書き手の意図が言語仕様とズレた時、コンパイラは何も言わずに動いてしまう」という危うさでもある。

中でも`INITIAL`属性は、単なる初期値の設定ツールではない。その変数の「ストレージクラス」によって、挙動が劇的に変わることを忘れてはならない。

2. 「宣言時」と「再呼び出し時」の決定的な違い

現場でよく見るミスは、静的変数(STATIC)に`INITIAL`をつけたまま、何度も呼び出されるサブルーチン内で値を再利用しようとするケースだ。

/i
/ — 悪い例:意図せず値が引き継がれてしまう — /
CALC_TOTAL: PROC(IN_VAL) ;
DCL IN_VAL FIXED BIN(31) ;
DCL WORK_SUM FIXED BIN(31) STATIC INITIAL(0) ;

/ ここでWORK_SUMが前回実行時の値を持ってしまっている! /
WORK_SUM = WORK_SUM + IN_VAL ;
PUT SKIP LIST(‘現在の合計:’ || WORK_SUM) ;
END CALC_TOTAL ;

このコードでは、`WORK_SUM`はプログラムロード時に一度だけ`0`で初期化される。つまり、サブルーチンを2回目に呼んだ時、`WORK_SUM`は`0`ではなく、前回の計算結果が残っている。これを「バグ」と見るか「累積機能」と見るかは設計次第だが、意図しない挙動であれば致命的だ。

3. 実践:VSAMバッチ処理での「安全な初期化」パターン

基幹バッチでVSAMを叩く際、レコード毎にワークエリアをクリアするのは鉄則だ。`INITIAL`に頼りすぎず、明示的な代入や`ASSIGN`(構造体の場合は`EMPTY`も視野に)を組み合わせるのが、トラブルを未然に防ぐベテランの流儀だ。

/i
/ — 安全な初期化の作法 — /
PROCESS_REC: PROC ;
DCL VSAM_BUFFER CHAR(256) ;
DCL ERR_FLG BIT(1) INITIAL(‘0’B) ; / 処理毎にリセットしたい /

/ ONユニットでエラーを捕捉しつつ、変数をクリーンに保つ /
ON ENDFILE(VSAM_FILE) BEGIN ;
PUT SKIP LIST(‘EOF検出。終了処理を実行。’) ;
END ;

DO WHILE(STATUS_OK) ;
/ 処理のループ内で変数を明示的にリセット /
ERR_FLG = ‘0’B ;

READ FILE(VSAM_FILE) INTO(VSAM_BUFFER) ;

IF SUBSTR(VSAM_BUFFER, 1, 1) = ‘E’ THEN DO ;
ERR_FLG = ‘1’B ;
/ 組み込み関数を活用してエラーログを出力 /
PUT SKIP LIST(‘エラー発生。レコード長:’ || LENGTH(VSAM_BUFFER)) ;
END ;
END ;
END PROCESS_REC ;

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

大規模なマイグレーションや改修において、最も恐ろしいのは「なぜここでこの値になっているのか?」が追えなくなることだ。

1. STATICは明示的に: プログラムのどこで値が保持されているか曖昧にしないこと。静的保持が必要な変数には、必ずコメントで「※STATICのため累積される」と明記せよ。
2. 自動変数(AUTOMATIC)を活用せよ: 基本的に、サブルーチン内で使い捨てのワーク変数は`STATIC`をつけないのが正解だ。デフォルトの`AUTOMATIC`であれば、プロシージャ呼び出しのたびにスタック上で領域が確保され、`INITIAL`属性は「呼び出しのたびに」再評価される。
3. BUILTIN関数の活用: `LENGTH`や`SUBSTR`といった組み込み関数を多用し、動的なバッファサイズにも耐えうるコーディングを心がけること。

PL/Iは、書き手が「メモリーをどう制御するか」を理解していれば、これほど頼りになる相棒はいない。`INITIAL`属性を単なる「便利な機能」と思わず、「メモリの生存期間(Extent)」を制御するツールとして使いこなしてほしい。

もし、デバッグ中に「値が消えない!」と嘆く後輩がいたら、まずはその変数の`STORAGE`属性を確認させること。それが、トラブルシューティングへの最短ルートだ。

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