【テクニカル・上級編】ON SIZEによる算術オーバーフローの検出 – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの「ON SIZE」と算術オーバーフロー:レガシーの深淵を読み解く

メインフレームの現場で長く生きていると、ある種の「悟り」に達することがある。PL/Iという言語は、一見するとCOBOLの厳格さとC言語の柔軟性を併せ持った贅沢な言語に見えるが、その実、極めて狡猾な側面を持っている。特に「予約語が存在しない」という設計思想は、現代の言語設計者から見れば狂気の沙汰だが、この仕様こそがPL/Iを「書く人の意図をすべて受け入れる(そして同時に裏切る)」言語たらしめているのだ。

今日は、その中でも特にバッチ処理の信頼性を左右する「ON SIZE」による例外処理と、それに潜むパフォーマンスの罠について、アーキテクトの視点から紐解いていこう。

1. 予約語なき世界の流儀とON SIZEの罠

PL/Iには、いわゆる「予約語」が存在しない。`IF` や `THEN` といったキーワードであっても、プログラマが変数名として定義してしまえば、コンパイラはそれを識別子として解釈する。これは自由度が高い反面、後続の保守担当者にとっては悪夢だ。

さて、基幹システムの算術演算において、`FIXED DECIMAL`(パックデシマル)が桁溢れを起こした際、何も対策を講じていなければ、システムは無慈悲にS0C7やS0CBでアベンドする。ここで登場するのが `ON SIZE` 条件だ。

/i
/ パックデシマルの桁溢れを検知するONユニット /
DCL A FIXED DEC(5,0) INIT(99999);
DCL B FIXED DEC(5,0) INIT(2);
DCL RESULT FIXED DEC(5,0);

ON SIZE BEGIN;
/ 溢れた場合のリカバリ処理。ログ出力やデフォルト値代入など /
PUT SKIP LIST(‘算術オーバーフロー発生。計算結果が変数の精度を超えました。’);
RESULT = 0; / 安全な値にフォールバック /
END;

/ ここで桁溢れが発生し、ONユニットが制御を奪う /
RESULT = A B;

一見スマートだが、現場レベルでは「ONユニットの多用は禁忌」という不文律がある。

2. なぜ「SIZE」オプションがパフォーマンスを殺すのか

コンパイラオプションの `SIZE` を有効にすると、PL/Iコンパイラはすべての算術演算に対して「結果が変数の精度内に収まっているか」というチェックコードを機械的に挿入する。

現代の高速なCPUであっても、この「命令の合間に挟まる条件分岐」のオーバーヘッドは馬鹿にならない。数百万件を処理するバッチプログラムにおいて、このチェックが毎回走ることは、CPU時間を著しく浪費させる。

アーキテクトの知見:最適化の定石

もし、ロジック上「絶対に溢れない」ことが保証されているのであれば、本番環境では `NOSIZE` オプションでコンパイルし、チェックを外すのがレガシー移行前の定石だ。ただし、これを行うには、入力データのバリデーションが完璧であるという絶対的な確信が必要となる。

3. マイグレーションにおける「埋め込みSQL」との遭遇

JavaやC#への移行を検討する際、最も頭を悩ませるのがDB2の埋め込みSQLとPL/Iのデータ型の不整合だ。

PL/Iで定義された `FIXED DEC` は、内部的にパックデシマル(1バイトに2桁)で保持される。Javaの `BigDecimal` との比較や、C#の `decimal` との型変換において、この「符号ビットの反転」や「桁精度の解釈」の違いがバグの温床となる。

特に、CICSオンライン処理において、画面から入力された値をパックデシマルで計算し、それをDB2へ格納する際、`ON SIZE` が効かない条件下で `SQLCODE -802`(算術例外)が発生すると、アプリケーション側では原因の特定が困難になる。この時、ダンプを解析して「なぜその値になったのか」を追う力こそが、我々アーキテクトに求められる「真の技術力」だ。

4. 実践:ポインタとベース変数によるメモリ制御

動的なメモリ管理において、`BASED` 属性を用いた構造体の操作は、PL/Iの最も強力な武器だ。

/i
DCL BUFFER_PTR PTR;
DCL 1 MY_RECORD BASED(BUFFER_PTR),
2 FIELD_A FIXED DEC(5),
2 FIELD_B CHAR(10);

/ 動的にメモリを確保 /
ALLOCATE MY_RECORD;

/ ポインタ経由で計算処理 /
MY_RECORD.FIELD_A = MY_RECORD.FIELD_A 2;

このポインタ操作を乱用すると、メモリ破壊(オーバーレイ)を引き起こし、原因不明のアベンドを誘発する。移行プロジェクトでは、こうした「ポインタによる強引なメモリ操作」が現代言語の安全なメモリ管理モデルと衝突する。移行時には、単なるコード変換ではなく、このメモリレイアウト自体を「JavaのPOJO」や「C#のクラス」へいかに安全に写像するかが、システムの信頼性を決定づける。

結論:技術の橋渡しとしてのアーキテクト

PL/Iのコードを読んでいると、30年以上前に書かれたロジックが、今なお基幹システムの心臓部を動かしていることに驚かされる。`ON SIZE` を使いこなすことは、単なる構文の習得ではない。それは、システムが限界を迎えた瞬間に、いかにして「優雅に死ぬ(あるいは生き延びる)」かを設計する、アーキテクトの矜持そのものなのだ。

レガシー移行は、過去の資産を破壊する作業ではない。コードに込められた設計意図を汲み取り、それを現代のプラットフォームで再構築する「翻訳」の作業である。

もし貴方のプロジェクトで、突然の算術アベンドが収束しないなら、それはコンパイラが「お前のロジックにはまだ甘さがある」と教えてくれているのかもしれない。

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