現場のエンジニアへ:FIXED BINARYの「2バイトと4バイト」がバグの温床になる理由
メインフレームの保守現場で、なぜか特定の値で計算が狂う、あるいは不可解なオーバーフローでバッチがアベンドする。そんな経験はないだろうか?
「たかだか整数型だろう」と高を括っていると、足元をすくわれるのがPL/Iの`FIXED BINARY`だ。特に、`FIXED BINARY(15)`と`(31)`の内部表現の違いを理解していないと、マイグレーション先や既存の複雑なロジックの中で致命的なミスを招く。今日は、長年メインフレームの現場で揉まれてきた経験から、この「バイナリの罠」について深掘りしていく。
—
1. 内部表現:なぜ「15」と「31」なのか
まず基本だが、PL/Iにおいて`FIXED BINARY(n)`の`n`は、ビット数を指している。
- FIXED BINARY(15): 2バイト(16ビット)を使用。1ビットは符号(正負)に使われるため、有効範囲は `-32,768` から `32,767`。いわゆる「ハーフワード」だ。
- FIXED BINARY(31): 4バイト(32ビット)を使用。1ビットは符号のため、有効範囲は `-2,147,483,648` から `2,147,483,647`。いわゆる「フルワード」だ。
ここが重要だ。 コンパイラは、演算の際にこれらの属性をどう扱うか。例えば、`FIXED BIN(15)`同士を足し合わせた場合、結果は自動的に`FIXED BIN(15)`として処理されようとする。ここで合計値が `32,767` を超えると、何の警告もなく上位ビットが切り捨てられ、数値が反転する(あるいは予期せぬマイナス値になる)という、バッチ処理における「悪夢」が発生する。
—
2. 実践的コーディング:ONユニットでオーバーフローを飼いならす
バッチ処理で最も怖いのは「計算エラーで止まること」以上に「計算エラーに気づかずデータを破壊すること」だ。PL/Iには強力な`ONユニット`がある。これを活用し、万が一のオーバーフローを検知する防御壁を築くのが、熟練のやり方だ。
1
/ ————————————————————- /
/ プログラム名: CALC_SAMPLE /
/ 内容: FIXED BINARY演算の安全な制御とONユニットの実装 /
/ ————————————————————- /
CALC_SAMPLE: PROCEDURE OPTIONS(MAIN);
DCL H_VAL FIXED BIN(15) INIT(30000); / ハーフワード /
DCL F_VAL FIXED BIN(31) INIT(0); / フルワード /
DCL MSG_FLAG FIXED BIN(1) INIT(0);
/ オーバーフロー発生時の制御を定義 /
ON FIXEDOVERFLOW BEGIN;
PUT SKIP LIST(‘警告: 計算結果が範囲を超過しました’);
MSG_FLAG = 1;
END;
/ 計算ロジック /
/ 15ビット同士の演算は暗黙的に15ビットで行われるため注意が必要 /
F_VAL = H_VAL + 5000;
IF MSG_FLAG = 0 THEN
PUT SKIP LIST(‘計算成功。結果は:’ || F_VAL);
ELSE
PUT SKIP LIST(‘異常終了: 計算精度不足’);
RETURN;
END CALC_SAMPLE;
—
3. VSAM入出力とマイグレーションの現場から
既存のVSAMファイルを読み込む際、Copybook(コピーブック)上の定義が`PIC S9(4) COMP`となっている場合、それはPL/Iでは`FIXED BIN(15)`として読み込むのが定石だ。
しかし、マイグレーションやリコンパイルの際、うっかり`FIXED BIN(31)`として定義し直してしまったらどうなるか?
内部的なメモリレイアウトがズレるため、レコードの読み込み時にデータが化ける。あるいは、上位桁にゴミデータが残ったまま計算が進み、テスト工程では見抜けない「静かなバグ」となる。
実務でのチェックポイント
- 計算対象の変数は極力`FIXED BIN(31)`で統一する: 現代のCPUアーキテクチャにおいて、ハーフワード演算とフルワード演算の性能差は無視できる。中途半端に`FIXED BIN(15)`を使うメリットはメモリ節約以外ほとんどない。
- 組み込み関数の活用: `BINARY(expr, 31)`のように、計算時に明示的に精度を指定する癖をつけること。
1
/ 精度を明示的に変換して安全に演算する /
RESULT = BINARY(VAL_A, 31) + BINARY(VAL_B, 31);
—
最後に:アーキテクトからの助言
PL/Iは、その自由度の高さゆえに、書き手のスキルがコードの品質に直結する言語だ。`FIXED BIN(15)`と`(31)`の違いを理解することは、単なる仕様の把握ではなく、「システムにどれだけ堅牢なガードレールを設置できるか」というプロ意識の表れである。
改修の際、もし古いソースコードで`FIXED BIN(15)`が多用されている箇所を見つけたら、まずはその計算ロジックが将来的なデータ量増加に耐えうるかを確認してほしい。それが、長年この世界で生き残るシステムエンジニアの「勘所」だ。
今日の解説が、あなたのコードを少しでも堅牢なものにする手助けとなれば幸いだ。現場でまた、難解なバグに直面したら相談してくれ。
