PL/Iの「境界」を制する者は、レガシー移行を制す ― HBOUNDとLBOUNDの深淵
基幹システムの保守やマイグレーションの現場で、最も神経を使う作業の一つが「配列の境界判定」です。特に、何十年も前に書かれたPL/Iのコードベースにおいて、`HBOUND`と`LBOUND`は単なるビルトイン関数ではありません。これらは、メモリの安全圏と、システムを崩壊させる領域との境界線そのものです。
今日は、JavaやC#への移行を控えたテックリードの諸君に向けて、この関数の「真の姿」と、それが引き起こすかもしれない悪夢について語りましょう。
1. なぜ「固定宣言」を過信してはいけないのか
多くの開発者は、`DCL ARR(10) FIXED BIN(31);` のような宣言を見て、「配列は常に10要素だ」と思い込みます。しかし、PL/Iの真骨頂は、サブルーチンへ渡された際の「基底(Base)」の曖昧さにあります。
/i
/ 配列の境界を安全に取得する典型的な手法 /
PROCESS_ARRAY: PROC(P_ARRAY);
DCL P_ARRAY() FIXED BIN(31) BASED(ADDR_PTR);
DCL (L_IDX, H_IDX) FIXED BIN(31);
/ ここで境界値を取得。引数として渡された配列のサイズを動的に判定 /
L_IDX = LBOUND(P_ARRAY, 1);
H_IDX = HBOUND(P_ARRAY, 1);
DO I = L_IDX TO H_IDX;
/ ここでP_ARRAY(I)にアクセスする際、境界外参照のリスクを排除できる /
END;
END PROCESS_ARRAY;
このコードのポイントは、`DCL P_ARRAY()` と宣言することで、ポインタ経由で渡されたメモリ領域の境界を、コンパイラに「都度計算させる」点にあります。移行先のJavaで言えば `array.length` に相当しますが、PL/Iではこれがコンパイラ生成のデスクリプタ(Dope Vector)を参照して解決されるため、ランタイムのオーバーヘッドを意識する必要があります。
2. 移行現場で遭遇する「地雷」:パックデシマルの罠とアベンド
マイグレーション中、最も泣かされるのがパックデシマル(FIXED DEC)の内部表現と境界値の衝突です。
配列の添字計算に `FIXED BIN` を使っているつもりが、実は内部で `FIXED DEC` との暗黙の変換が行われ、最下位ニブルの符号(C/D/F)がバグの温床になるケースがあります。特に、`HBOUND`で取得した値を添字としてループを回す際、コンパイラオプションの `SUBSCRIPTRANGE` が無効になっていると、メモリ破壊を起こしてもアベンド(S0C4など)せずに、サイレントにデータを汚染し続けることがあります。
現場の知見:アベンド解析の勘所
もし、`HBOUND`の戻り値が期待値と異なる場合、まずは以下の3点を疑ってください。
1. コンパイラオプション `RULES(IBM)` か `RULES(ANS)` か: 配列添字の解釈や境界チェックの厳密さが異なります。
2. ストレージ・オーバーレイ: `DEFINED` 属性を使ってメモリを重ねている箇所がないか。`HBOUND`の結果が変わるわけではありませんが、計算後のインデックスで隣接する変数を破壊していないかを確認すべきです。
3. CICSの通信領域(COMMAREA): 外部システムから渡されたデータの境界を `HBOUND` で判定する際、相手側の定義とこちらの `DCL` が1バイトでもズレていれば、その先は地獄です。
3. Java/C#移行へ向けて:アーキテクチャの転換点
Javaへの移行時、`HBOUND`をどのようにマッピングすべきでしょうか。単純な `for` ループへの変換は危険です。
PL/Iの配列は、デフォルトで `LBOUND` が 1 とは限りません。`DCL A(0:9)` のように、オフセットを持たせるケースが多々あります。これをJavaの `0` スタートの `ArrayList` や配列に強引に詰め込むと、境界判定のロジックで致命的な「Off-by-oneエラー」を引き起こします。
私からの提言:
マイグレーションツールに頼り切るのではなく、まずソースコードの `LBOUND` が `1` 以外を返すケースを全件洗い出してください。それこそが、旧来の汎用機システムが持つ「物理メモリ上の位置関係に対する執着」を、現代的な「論理データ構造」へと昇華させる唯一の道です。
結びに代えて
`HBOUND` と `LBOUND` を使いこなすことは、単なる構文の習得ではありません。それは、コンパイラがメモリをどのように管理し、CPUがどのオフセットを叩いているのかという「汎用機の鼓動」を感じ取ることと同義です。
基幹システムのコードは、時に難解で無愛想です。しかし、そこに刻まれた「境界」の意味を理解できたとき、初めて私たちは、レガシーという名の巨大な遺産を、次世代へと安全にバトンタッチできるのです。
システムアーキテクトとして、また一人のPL/Iエンジニアとして、皆さんの移行プロジェクトが「境界外アクセス」なく成功することを願っています。
