1. 導入:なぜ「定数」の書き換えが危険なのか
メインフレーム(z/OS)の開発現場では、COBOLなどの言語で手続き(プロシージャ)を呼び出す際、引数を渡すことがあります。このとき、リテラル(’A’のような直接記述された値)を「書き換え可能な引数」として受け取ってしまうコードが、重大なシステム異常(アベンド)の原因になることがあります。なぜなら、定数はメモリ上の「読み取り専用領域」に配置されていることが多く、そこへ無理やり書き込みを行おうとすると、OSが不正アクセスとしてプログラムを強制終了させるからです。
2. 基礎知識:参照渡しとメモリ保護の仕組み
メインフレームのプログラミングでは、引数を渡す際に「参照渡し(アドレスを教える)」という方式が一般的です。
参照渡しとは、値そのものではなく「値が置いてある場所(メモリアドレス)」を呼び出し先に伝える方法です。
通常、変数であればそのアドレスへ値を書き込んでも問題ありません。しかし、プログラム内に直接書いた定数(リテラル)は、OSによって「ここは変更してはいけない場所」と厳格に保護されています。この保護領域を不用意に操作しようとすると、OSによるメモリ保護機能が働き、プログラムは「S0C4アベンド(保護違反)」などで停止してしまいます。
3. 実装/解決策:安全な引数の扱い方
このリスクを回避するための解決策は非常にシンプルです。「書き換える可能性のある値は、必ず作業用変数(ワークエリア)にコピーしてから渡す」というルールを徹底することです。呼び出し先(サブプログラム)で値を変更する可能性があるなら、呼び出し元で一旦変数に値をセットし、その変数を渡すようにしてください。
4. サンプルプログラム:安全な引数の渡し方(COBOL例)
WORKING-STORAGE SECTION.
01 WS-WORK-VAL PIC X(05).
PROCEDURE DIVISION.
MAIN-PROCEDURE.
- 悪い例:定数をそのまま渡すと、サブ側で書き換えが発生した際にアベンドする
- CALL ‘SUB001’ USING ‘ABCDE’.
- 良い例:一度変数に代入してから渡す
MOVE ‘ABCDE’ TO WS-WORK-VAL.
CALL ‘SUB001’ USING WS-WORK-VAL.
STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB001.
LINKAGE SECTION.
01 LK-VAL PIC X(05).
PROCEDURE DIVISION USING LK-VAL.
- ここでLK-VALに値を代入しても、呼び出し元の変数が書き換わるだけで
- メモリ保護違反(アベンド)は発生しない
MOVE ‘NEW’ TO LK-VAL.
GOBACK.
5. 応用・注意点:レガシーコードの移行時には要注意
古いメインフレームのシステムでは、メモリ保護の設定が甘かった時代に書かれた「定数領域をわざと書き換えてフラグとして使う」という危険なハックが存在することがあります。もし古いコードを現代の環境へ移行する場合、これらは間違いなくアベンドの原因になります。
注意すべきポイント:
・プログラム中の CALL 文を確認し、引数がリテラル(引用符で囲まれた定数)になっていないかチェックする。
・サブプログラム側で、受け取った引数を「出力用」として再利用していないか確認する。
もし既存のプログラムでリテラルを渡している箇所を見つけたら、面倒でも上記サンプルのように「一度変数に退避させる」修正を行うことを強く推奨します。これが安定したメインフレーム運用のための第一歩です。

コメント