【COBOL学習|豆知識】COBOLのCALL文における「リテラル」の取り扱いと内部動作の秘密

導入

COBOLの外部プログラム呼び出し(CALL文)において、引数に直接リテラル(定数)を記述することはよくあります。しかし、なぜリテラルを渡せるのか、内部でどのような処理が行われているのかを意識したことはあるでしょうか?この仕組みを理解することは、メモリ保護や予期せぬバグを防ぐための重要な第一歩です。

基礎知識

COBOLのCALL文には、引数を渡す方法として「BY REFERENCE(参照渡し)」と「BY CONTENT(値渡し)」の2種類が存在します。
通常、変数を渡す場合はBY REFERENCEがデフォルトですが、リテラル(”ABC”のような定数)を渡す場合には、コンパイラによって自動的に「BY CONTENT」として扱われます。

なぜなら、リテラルはプログラム内の「読み取り専用領域」に配置されていることが多く、呼び出し先でその値を書き換えてしまうと、プログラム全体で定数が破壊される危険があるからです。そのため、コンパイラは安全を期して、リテラルのコピーを一時的なメモリ領域に作成し、そのアドレスを渡すという仕組みをとっています。

実装/解決策

手続きの外部連携において、リテラルを渡す際は、以下の点に注意してください。
1. 呼び出し先プログラム(SUB)側では、受け取る項目は「変更不可」として扱うこと。
2. 呼び出し先での変更が呼び出し元に影響しないことを理解すること。
3. 明示的に記述する場合は「CALL “SUB” USING BY CONTENT “CONSTANT-DATA”」と書くことも可能ですが、リテラルの場合は省略しても自動的にこの挙動になります。

サンプルプログラム

以下のコードは、リテラルを呼び出し先に渡す基本的な例です。

IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-PROG.

PROCEDURE DIVISION.
> リテラルを渡す場合、自動的にBY CONTENTとして扱われます
CALL “SUB-PROG” USING “HELLO-COBOL”
STOP RUN.

IDENTIFICATION DIVISION.
PROGRAM-ID. SUB-PROG.

DATA DIVISION.
LINKAGE SECTION.
01 L-DATA PIC X(12).

PROCEDURE DIVISION USING L-DATA.
> L-DATAには”HELLO-COBOL”がコピーされています
DISPLAY “受け取った値: ” L-DATA

> 注意: ここでL-DATAを変更しても、呼び出し元のリテラルには影響しません
> また、リテラルを渡しているため、書き換えは論理的に避けるべきです
EXIT PROGRAM.

応用・注意点

現場での開発において、特に注意すべきは「呼び出し先プログラムのLINKAGE SECTIONの定義」です。
呼び出し側がリテラル(BY CONTENT)で渡しているにもかかわらず、呼び出し先プログラムでその値を書き換えるロジックを組んでしまうと、予期しない動作やコンパイラの最適化によって異常終了を招く恐れがあります。

鉄則として、「BY CONTENTで受け取ったデータは、呼び出し先では絶対に書き換えない(読み取り専用として扱う)」というルールをコーディング規約に盛り込むことを強く推奨します。また、リテラルの長さとLINKAGE SECTIONの項目長が一致しているかどうかも、メモリ破壊を防ぐために必ず確認するようにしましょう。

コメント

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