Debugging: DISPLAY, Abends and Dumps

COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x · ✓ verified by execution on 2026-08-16

Preventing the Dreaded Abend

In the world of COBOL, especially on mainframes, a program crash is known as an Abend (Abnormal End). The most infamous of these is the data exception (often referred to as an S0C7 on IBM mainframes). Data exceptions occur when a program attempts to perform arithmetic on a numeric field that contains non-numeric data, such as spaces or alphabetic characters.

Because COBOL does not enforce types dynamically, it is entirely possible to read garbage data from a file into a numeric variable. The program will not crash during the MOVE or READ statement; it silently corrupts memory and waits to explode later during a COMPUTE or ADD operation.

Here is a visual representation of how a data exception happens in memory:

MOVE 'XY' TO WS-TXT XY (Invalid) ADD 1 TO WS-NUM 💥 DATA EXCEPTION 💥

Simulating a Data Exception

Let’s look at exactly how this happens in code. Notice how we use REDEFINES to bypass the compiler’s type checks.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. BAD-DATA.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-NUM PIC 99.
       01 WS-TXT REDEFINES WS-NUM PIC XX.
       PROCEDURE DIVISION.
           MOVE 'AB' TO WS-TXT
           ADD 1 TO WS-NUM
           DISPLAY 'FINISHED' WS-NUM
           STOP RUN.
Output
FINISHED13

In standard IBM environments, the ADD 1 TO WS-NUM line would trigger an immediate S0C7 hardware interrupt and produce a memory dump. In our GnuCOBOL learning environment, it exhibits a silent corruption behavior, calculating a garbage result (FINISHED13) rather than crashing.

To prevent these errors, you must always validate incoming data before using it in mathematical operations. But notice that memory corruption doesn’t actually crash until math happens.

Predict the output cobol

Read the code. What exactly will it print? Commit to an answer before you look.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SILENT-CORRUPT.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-NUM PIC 99.
       01 WS-TXT REDEFINES WS-NUM PIC XX.
       PROCEDURE DIVISION.
           MOVE 'XY' TO WS-TXT
           *> Question: What happens when we DISPLAY a numeric field 
           *> that contains letters? Will it abend or print 00?
           DISPLAY 'VALUE: ' WS-NUM
           STOP RUN.
Output
VALUE: XY

The Poor Man’s Debugger: DISPLAY

In modern programming, you might be used to step-through debuggers. In legacy COBOL environments, these tools were often unavailable. The most reliable way to find the exact line that caused an abend is by strategically placing DISPLAY statements to track the execution flow.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DEBUG-DISP.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-COUNT PIC 9 VALUE 1.
       PROCEDURE DIVISION.
           DISPLAY 'ENTERED PROCEDURE DIVISION'.
           PERFORM UNTIL WS-COUNT > 3
               DISPLAY 'WS-COUNT IS NOW: ' WS-COUNT
               ADD 1 TO WS-COUNT
           END-PERFORM.
           DISPLAY 'EXITING PROGRAM'.
           STOP RUN.
Output
ENTERED PROCEDURE DIVISION
WS-COUNT IS NOW: 1
WS-COUNT IS NOW: 2
WS-COUNT IS NOW: 3
EXITING PROGRAM

Advanced Tracing and Exceptions

If DISPLAY statements are not enough, compilers offer built-in debugging features. GnuCOBOL can check exceptions using the ON EXCEPTION clause (Exceptions may also be enabled/disabled separately) and can generate code for specific exceptions using the -fec flag (enable code generation for exception-name).

Additionally, GnuCOBOL offers a COB_SET_TRACE environment variable to enable the COBOL trace feature.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TRACE-VAR.
       PROCEDURE DIVISION.
           DISPLAY 'TRACING TEST'.
           STOP RUN.
Output
TRACING TEST

Compile-Time Debugging Lines

Instead of manually deleting DISPLAY statements before moving your code to production, COBOL allows you to define “debugging lines.” In free-format COBOL, these lines start with >>D.

The -fdebugging-line compiler option enables debugging lines. By default, they are completely ignored by the compiler. However, WITH DEBUGGING MODE activates USE FOR DEBUGGING procedures during compile-time because of WITH DEBUGGING MODE.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DEBUG-LINE.
       PROCEDURE DIVISION.
           DISPLAY 'NORMAL RUN'.
       >>D DISPLAY 'DEBUG LINE ACTIVATED'.
           STOP RUN.
Output
NORMAL RUN

If we activate DEBUGGING MODE, the line will execute:

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DEBUG-MODE.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER. COMPUTER-NAME WITH DEBUGGING MODE.
       PROCEDURE DIVISION.
           DISPLAY 'DEBUG MODE DEMO'.
       >>D DISPLAY 'DEBUG LINE ACTIVATED'.
           STOP RUN.
Output
DEBUG MODE DEMO
DEBUG LINE ACTIVATED

Bug Hunt: Prevent the Abend

Check yourself

What happens in COBOL if you move alphanumeric characters into a numeric field and then perform addition?

Reveal answer

The data is moved, but the ADD statement causes a runtime abend (like an S0C7) due to invalid digits. — COBOL does not enforce dynamic typing during MOVE. The invalid data corrupts memory silently, and the abend only happens when math is attempted.

How do you activate debugging lines starting with >>D in free-format COBOL?

Reveal answer

By compiling with the -fdebugging-line flag AND using WITH DEBUGGING MODE in SOURCE-COMPUTER. — Free-format debugging lines (>>D) require the compiler flag to parse them, and WITH DEBUGGING MODE to actually execute them.

Why is the DISPLAY statement often called a 'poor man\'s debugger' in COBOL?

Reveal answer

Because in mainframe environments without interactive debuggers, placing DISPLAYs is the most reliable way to track execution flow before an abend. — DISPLAY is a simple but critical tool for locating the exact paragraph where a program crashes when modern debuggers aren't available.

Challenges

🐞 Bug Hunt +50 XP

Fix the S0C7 abend waiting to happen! We are about to ADD 10 to a field that contains garbage ('XY'). Use an IF statement and the IS NUMERIC test to ONLY perform the addition if WS-INPUT is valid. If it's invalid, move 0 to WS-INPUT instead.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

cobol ✓ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real — it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 — expects "FINAL VALUE: 00"
Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. FIX-S0C7.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INPUT PIC 99.
01 WS-GARBAGE REDEFINES WS-INPUT PIC XX.
PROCEDURE DIVISION.
    MOVE 'XY' TO WS-GARBAGE.
    IF WS-INPUT IS NUMERIC
        ADD 10 TO WS-INPUT
    ELSE
        MOVE 0 TO WS-INPUT
    END-IF.
    DISPLAY 'FINAL VALUE: ' WS-INPUT.
    STOP RUN.

Challenge 2 +50 XP

Modify the program so that the trace message 'STARTING PROCESS' is only displayed if the program is compiled with debugging mode enabled (i.e. make it a free-format debugging line with >>D).

cobol ✓ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real — it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 — expects "STARTING PROCESS\nPROCESSING COMPLETE"
Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. MAKE-DEBUG.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. HOST-COMP WITH DEBUGGING MODE.
PROCEDURE DIVISION.
>>D DISPLAY 'STARTING PROCESS'.
    DISPLAY 'PROCESSING COMPLETE'.
    STOP RUN.