導入:なぜ「桁落ち」がバグの温床となるのか
COBOL開発の現場において、MOVE文による「桁落ち(Truncation)」は、最も厄介なバグの一つです。C言語やJavaのようにコンパイル時に厳密なチェックが働く言語とは異なり、COBOLのMOVE文は、受取り側項目の桁数を超えた場合、上位桁を容赦なく切り捨てて処理を続行します。実行時にエラーメッセージが出ることもなければ、システムが異常終了することもありません。この「黙ってデータを捨てる」という挙動が、金額計算や在庫管理のような正確性が求められる業務において、致命的な不整合を引き起こす原因となります。
基礎知識:MOVE文とデータ項目の仕組み
COBOLのMOVE文は、送り側の値を「受取り側の定義に合わせて」格納します。ここで重要なのは、受取り側のデータ項目(PICTURE句)が、保持したい値の最大桁数に対して十分な大きさを持っているかという点です。
例えば、PICTURE 9(02) の項目に 1234 をMOVEすると、下位2桁の「34」だけが保持され、上位の「12」は消滅します。この挙動は、古い時代には計算機のメモリを節約するためのテクニックとして使われていたこともありましたが、現代のシステム開発においては、意図しないデータ破壊とみなすべきです。
実装・解決策:安全なデータ転送の作法
桁落ちを防ぐための鉄則は「受取り側の桁数を送り側より大きく定義すること」ですが、動的な計算結果を扱う場合は、以下の対策を講じるのがベテランの作法です。
1. COMPUTE文の利用:MOVEではなく、計算式として定義することで、中間結果を保持するデータ項目の長さを意識的に制御します。
2. サイズチェックの明示:重要な値を転送する直前に、IF文で値の範囲チェックを行うロジックを挟みます。
3. ON SIZE ERROR句の活用:算術演算を行う際は、必ずON SIZE ERROR句を記述し、桁あふれが発生した際に異常終了やエラーログ出力を行うよう制御します。
サンプルプログラム:安全な転送を検証するコード例
以下は、桁落ちの危険性と、それを回避・検知するための実装例です。
IDENTIFICATION DIVISION.
PROGRAM-ID. TRUNC-CHECK.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-VALUE-LONG PIC 9(04) VALUE 1234.
01 WS-VALUE-SHORT PIC 9(02).
01 WS-RESULT PIC 9(02).
PROCEDURE DIVISION.
> --- 危険な例:桁落ちが発生しても何も通知されない ---
MOVE WS-VALUE-LONG TO WS-VALUE-SHORT.
DISPLAY "桁落ち後の値: " WS-VALUE-SHORT.
> 出力結果は「34」となり、上位の「12」は消滅する
> --- 安全な例:サイズチェックを行う ---
IF WS-VALUE-LONG > 99 THEN
DISPLAY "エラー:値が大きすぎます"
ELSE
MOVE WS-VALUE-LONG TO WS-RESULT
END-IF.
> --- 算術演算での対策:ON SIZE ERROR句 ---
COMPUTE WS-RESULT = WS-VALUE-LONG + 10
ON SIZE ERROR
DISPLAY "警告:計算結果が桁あふれしました"
END-COMPUTE.
STOP RUN.
応用・注意点:現場で陥りやすいバグの回避策
現場で特に注意すべきは、「再定義(REDEFINES)」や「グループ項目」のMOVEです。グループ項目で一括転送を行うと、個々の項目の桁数を意識する機会が減り、知らないうちに桁落ちが発生しているケースが多々あります。
また、外部連携ファイルから読み込んだデータが、定義よりも大きい桁数で送られてくることも想定しておくべきです。常に「データは壊れる可能性がある」という前提に立ち、特に金額や数量を扱う項目では、受取り側の桁数をあえて大きめに確保しておくのが、COBOL技術者としての健全な防御策です。安全はプログラムの構造から作り込みましょう。

コメント