PL/Iの「落とし穴」:FIXED BIN(15)と(31)が引き起こす静かなる破壊
メインフレームの現場で長年コードを読んでいると、後輩から「なぜか突然ABEND(S0C1やS0C7ではない、謎のデータ異常)が発生した」という相談を受けることがよくあります。その原因の多くは、実は`FIXED BINARY`の精度指定――(15)か(31)か――という、一見些細な設計ミスに端を発しています。
今日は、この「2進整数」の深淵について、現場の知見を交えて徹底解説します。
—
1. なぜFIXED BIN(15)と(31)を使い分ける必要があるのか
まず基本の整理ですが、PL/Iにおいて`FIXED BIN(n)`の`n`は「ビット数」を指します。
- FIXED BIN(15): 2バイト(16ビット)を占有。符号ビットを除き、表現可能な範囲は -32,768 ~ 32,767。
- FIXED BIN(31): 4バイト(32ビット)を占有。表現可能な範囲は -2,147,483,648 ~ 2,147,483,647。
「とりあえず大きいほうが安全だろう」と全て(31)にするのは、メモリ制約が厳しかった時代の名残で悪手とされることもありますが、現代のメインフレームでは基本は(31)で設計し、外部インターフェース(COBOL連携や固定長ファイル)との整合性が求められる場合にのみ(15)を選択するのが鉄則です。
ここで最も恐ろしいのは、「暗黙の型変換」と「オーバーフロー」です。
—
2. 現場で遭遇する「静かなるオーバーフロー」
下のコードを見てください。一見、何の問題もないように見えますが、実務では致命傷になり得ます。
1
/ —————————————————————— /
/ サンプル:整数演算における精度の罠 /
/ —————————————————————— /
TEST_PROC: PROCEDURE OPTIONS(MAIN);
DCL COUNT_S FIXED BIN(15) INIT(0); / 15ビット(小規模カウンター用) /
DCL COUNT_L FIXED BIN(31) INIT(0); / 31ビット(安全策) /
DCL TOTAL FIXED BIN(31);
/ ONユニットでオーバーフローを捕捉する設計は必須 /
ON FIXEDOVERFLOW BEGIN;
PUT SKIP LIST(‘警告: 整数オーバーフローが発生しました’);
END;
/ 32767を超えると、COUNT_Sは「符号反転」という異常値を引き起こす /
COUNT_S = 32767;
COUNT_S = COUNT_S + 1;
/ このとき、COUNT_Sは -32768 に化ける /
/ 後続のファイル出力やVSAMのキー検索で予期せぬ挙動を引き起こす /
TOTAL = COUNT_S 100;
PUT SKIP LIST(‘RESULT:’, TOTAL);
END TEST_PROC;
なぜこれが怖いのか?
PL/Iのコンパイラは、演算結果が一時的に`FIXED BIN(31)`の精度を必要とする場合、自動的に内部で昇格を行います。しかし、代入先の変数が`FIXED BIN(15)`である場合、実行時に切り捨てや符号ビットの誤判定が起きても、コンパイラは必ずしもエラーを吐きません。
特に古いライブラリを呼び出す際、`FIXED BIN(15)`を期待している場所に(31)を渡すと、上位ビットがパージされて予期せぬ値になるケースは、デバッグ泣かせの筆頭です。
—
3. コンパイラ最適化と実務上の対策
現代の`ENTERPRISE PL/I`コンパイラは非常に優秀です。`OPTIMIZE(2)`や`(3)`を指定すると、ループ内での整数演算はレジスタに保持され、メモリへの書き込みが遅延されます。
ここで重要なのは、「境界チェックのコスト」を恐れないことです。
- `LIMITS(FIXEDBIN(15|31))`の活用: コンパイルオプションで精度を強制的にチェックさせる設定は、大規模改修時には必ず有効にしてください。
- ONユニットの戦略的配置: `ON FIXEDOVERFLOW`は、プログラムの局所的なスコープで定義することで、特定の計算ロジックにおける異常を即座に捕捉できます。
- BUILTIN関数の活用: `BINARYVALUE`や`FIXED`関数を使い、演算の途中で意図的に精度を揃えるコーディングを心がけてください。
—
4. ベテランからのアドバイス:保守時に意識すべきこと
もし皆さんが、他人が書いたソースを改修する立場にあるなら、以下の手順を徹底してください。
1. DCL宣言を徹底的に洗う: 「特に理由なく`FIXED BIN(15)`が使われていないか」を確認してください。もしそれがレコードレイアウトの一部でなければ、躊躇なく`(31)`へ書き換えるべきです。
2. VSAMアクセス時の型合わせ: VSAMのキー定義が`PIC S9(4) COMP`(COBOL)の場合、PL/I側は必ず`FIXED BIN(15)`で宣言してください。ここが一致していないと、キー検索がヒットしないという現象に数日悩まされることになります。
3. コンパイラ・リスティングの確認: `OFFSET`マップを確認し、コンパイラがどの変数をどのレジスタに割り当てているかを確認する癖をつけてください。
メインフレームの安定稼働は、こうした「たった数ビットの妥協」を許さない積み重ねから生まれます。`FIXED BIN`の精度一つをとっても、なぜその値なのか――その設計意図をコードに刻むことこそが、真のシステムアーキテクトへの第一歩です。
何か疑問があれば、いつでも聞いてください。コードは嘘をつきませんからね。
