【実務・中級編】ON SUBSCRIPTRANGEによる配列添字範囲外アクセスの検知 – PL/Iの基本構文とデータ制御実践ガイド

現場のエンジニアへ告ぐ:その「異常終了」、ON SUBSCRIPTRANGEで未然に防げ

メインフレームの保守現場で、夜中に叩き起こされる原因のトップランナーといえば、何と言っても「データ異常によるabend(異常終了)」だ。特に、配列の添字が境界を突き抜けてメモリ上の別データを破壊する、いわゆる「添字範囲外アクセス」は、その場では落ちず、後続の全く関係ない処理で致命的なエラーを引き起こすという、最も厄介な性質を持っている。

今回は、PL/Iにおけるこの「見えない爆弾」を検知するための最強の武器、『ON SUBSCRIPTRANGE』について、現場の作法を交えて解説しよう。

1. なぜ「SUBSCRIPTRANGE」が必要なのか

PL/Iは非常に強力な言語だが、その分、メモリ管理や配列操作に対しては「プログラマの自己責任」という側面が強い。コンパイル時のオプションでチェックを有効にしていない限り、配列の宣言(例:`DCL ARRAY(10) FIXED BIN(31);`)を超えて `ARRAY(11)` にアクセスしても、コンパイラは黙認する。

これが本番環境で発生すると、隣接する領域のデータが書き換わり、後続の業務ロジックが論理矛盾を起こす。デバッグ時にこの問題を見つけるには、開発環境において意図的に監視の網を張る必要があるのだ。

2. 実践:ONユニットによる検知の仕組み

PL/Iには「ON条件」という強力な割り込み制御機能がある。これは、特定のエラーが発生した際に、プログラムの制御を一時的に奪い、指定した処理を実行させる仕組みだ。

以下のコードを見てほしい。開発中、あるいはテスト環境でのデバッグ時には、この記述を必ず挿入する癖をつけておくべきだ。

/i
/ — 添字範囲外検知のデバッグ・サンプル — /
TEST_PROC: PROCEDURE OPTIONS(MAIN);

/ コンパイラに組み込み関数として認識させる /
DCL SUBSCRIPTRANGE CONDITION;
DCL (I, J) FIXED BIN(15);
DCL MY_ARRAY(5) FIXED BIN(31) INIT((5)0);

/ ONユニットの設定:添字範囲外が発生した瞬間にここへ飛ぶ /
ON SUBSCRIPTRANGE
BEGIN;
PUT SKIP LIST(‘ 警告: 添字範囲外へのアクセスを検知しました ‘);
PUT SKIP LIST(‘現在の不正添字値: ‘, ONCHAR); / ONCHARは不正な値を保持するBUILTIN /
/ 必要に応じてここでダンプを出すか、異常終了させるロジックを組む /
STOP;
END;

/ 意図的に境界を超える操作を行う /
DO I = 1 TO 6;
MY_ARRAY(I) = I 10;
PUT SKIP LIST(‘ARRAY(‘, I, ‘) = ‘, MY_ARRAY(I));
END;

END TEST_PROC;

このコードのポイント

  • ON SUBSCRIPTRANGE: これを記述することで、プログラムは「配列の境界監視モード」に入る。
  • ONCHAR / ONSOURCE: エラー発生時に、どの値が原因で不正アクセスが起きたのかを特定するための必須BUILTIN関数だ。
  • STOP: 検知した後に処理を続行させるのは危険だ。多くの場合、メモリ破壊を防ぐために、この時点で処理を停止させる判断が正しい。

3. 本番環境でのパフォーマンス影響と「引き際」

ここで重要な注意点がある。「本番環境でON SUBSCRIPTRANGEを有効にすべきか?」という問いだ。

答えは「NO」だ。

このチェック機能を有効にすると、全ての配列アクセスに対して境界チェックの命令が挿入される。数千万件のレコードを処理する基幹バッチでこれをやれば、CPU使用率は跳ね上がり、処理時間は数割増しになるだろう。

現場の知恵:実務での運用ルール

1. 開発・テストフェーズ: コンパイルオプション `SUBSCRIPTRANGE` を指定し、かつONユニットで明示的に検知する。
2. 本番フェーズ: コンパイルオプション `NOSUBSCRIPTRANGE` を指定し、チェック機能そのものをコードから削除(あるいはコメントアウト)する。

「動けば良い」というコードは、数年後の改修時に必ず自分たちの首を絞める。特にVSAMファイルを扱うような複雑なロジックでは、こうした境界チェックの有無が、システム全体の品質を決定づけると言っても過言ではない。

最後に:プロの矜持として

PL/Iのコードをメンテナンスするということは、先人が遺した「意図」を読み解く作業だ。もし君が現在担当しているプログラムで、一度もSUBSCRIPTRANGEを意識したことがないのであれば、一度、テスト環境でこのONユニットを組み込んで実行してみてほしい。

驚くべきことに、今まで「なぜかたまに発生していた謎のデータ破壊」が、実は配列の添字ミスだったことが発覚するかもしれない。

メインフレームの世界は、こうした地味な積み重ねを愛する者にこそ、微笑むものだ。さあ、今すぐソースを見直してみよう。健闘を祈る。

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