導入
COBOLのバッチ処理やオンライン処理において、サブプログラムを繰り返し呼び出すことは一般的です。しかし、一度呼び出したプログラムはメモリ上に常駐し、前回の処理で書き換わった「Working-Storage」の内容を保持し続けます。これにより、意図せず前回のデータが残ってしまうという「状態の汚染」がバグの温床となることがあります。この課題を解決し、安全にプログラムを再初期化するために必須となるのが「CANCEL文」です。
基礎知識
COBOLのサブプログラム(CALLされるプログラム)は、初めて呼び出された際にメモリへロードされます。その後、プログラムが終了(EXIT PROGRAM)しても、メモリ上のデータ領域は維持されます。この仕組みにより、次回のCALL時に前回の計算結果やフラグが残っているというメリットがある反面、初期化忘れによる論理エラーを引き起こすリスクも抱えています。CANCEL文は、このメモリ上に存在するプログラムのデータ領域を解放し、次に呼び出された際に、VALUE句で定義された初期値の状態から再スタートさせる役割を担います。
実装/解決策
CANCEL文を使用する際は、プログラム名を指定します。この文を実行すると、対象のプログラムがメモリから破棄されます。次に同じプログラムをCALLしたとき、システムは再びプログラムをメモリへロードし、Working-Storageの各項目をVALUE句の値でリセットします。重要なのは、「本当に初期化が必要なタイミングを見極めること」です。不要なCANCELはロード処理のオーバーヘッドを生むため、処理の区切りや、特定条件でのみ実行するのが現場の定石です。
サンプルプログラム
以下の例は、呼び出されるたびにカウンタを保持するプログラムと、それをリセットするメインプログラムのイメージです。
— メインプログラム —
PROCEDURE DIVISION.
- 1回目の呼び出し
CALL “SUBPROG”.
- 2回目の呼び出し(前回値が残っている)
CALL “SUBPROG”.
- ここでCANCELを実行してサブプログラムを破棄
CANCEL “SUBPROG”.
- 3回目の呼び出し(初期状態で実行される)
CALL “SUBPROG”.
STOP RUN.
— サブプログラム (SUBPROG) —
WORKING-STORAGE SECTION.
01 COUNTER PIC 9(05) VALUE 0.
PROCEDURE DIVISION.
ADD 1 TO COUNTER.
DISPLAY “現在のカウント値: ” COUNTER.
EXIT PROGRAM.
応用・注意点
現場で最も注意すべきは、「CANCEL文の乱用によるパフォーマンス低下」です。プログラムのロードはOSにとってコストのかかる処理です。頻繁に呼び出されるサブプログラムで毎回CANCELを実行すると、システム全体の処理時間が大幅に増大します。また、外部ファイルやデータベースの接続状態を管理しているプログラムを不用意にCANCELすると、接続の切断や再接続のコストが発生する可能性があります。
「ここぞ」という初期化が必要なタイミングでのみCANCELを使用し、それ以外では明示的なMOVE文による初期化を行うなど、メモリ管理と性能のバランスを考慮することが、ベテラン技術者の作法と言えるでしょう。

コメント