Writing Defensively

COBOL GnuCOBOL 3.2.0 · ✓ verified by execution on 2026-08-16

Writing defensive COBOL is all about trusting absolutely nothing—especially your own program’s working storage and any data handed to you from files or other systems.

In this lesson, we will explore the NUMERIC class test, the INITIALIZE statement, and level-88 condition names. These tools will help you defend against the dreaded S0C7 data exception abends.

The Danger of Uninitialized Memory

Unlike modern languages that automatically set integers to 0 and strings to empty, COBOL variables in the WORKING-STORAGE SECTION that lack a VALUE clause will contain whatever garbage data happened to be in that memory location previously.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. InitFields.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 REC-1.
          05 NUM-FIELD PIC 9(4).
          05 STR-FIELD PIC X(5).
       PROCEDURE DIVISION.
           INITIALIZE REC-1
           DISPLAY NUM-FIELD " " STR-FIELD
           STOP RUN.
Output
0000      

The INITIALIZE statement safely clears working storage variables. It sets numeric fields to zeros and alphanumeric fields to spaces, preventing unpredictable behavior. This is crucial because memory is just a block of bytes; until you explicitly write to it or define a VALUE, it holds whatever the previous program or OS operation left behind. You might assume your program starts with a clean slate, but relying on this without INITIALIZE or VALUE clauses will eventually cause your application to read phantom data from a prior transaction.

The NUMERIC Class Test

One of the most frequent causes of program crashes in COBOL is attempting to perform math on a numeric field (like PIC 9) that actually contains spaces, letters, or other non-numeric garbage data.

COBOL does not magically enforce that a PIC 9 only holds numbers. If invalid data enters the field, performing math will cause an abend (such as the infamous S0C7 data exception). Why does this happen? A PIC 9 tells the compiler how to interpret the memory bits, but if a file supplies the string “ABCD”, the processor attempts binary-coded-decimal arithmetic on those ASCII/EBCDIC letters and halts the program immediately.

cobol ✓ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. S0C7.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 BAD-NUM PIC 9(4) VALUE "ABCD".
       01 TOTAL   PIC 9(5) VALUE 0.
       PROCEDURE DIVISION.
           IF BAD-NUM IS NUMERIC
               ADD BAD-NUM TO TOTAL
           ELSE
               DISPLAY "CAUGHT"
           END-IF
           STOP RUN.
Output
CAUGHT

By testing IF field IS NUMERIC before operating on it, you can handle bad data gracefully.

BAD DATA PIC 9("ABCD") IS NUMERIC SAFE

The NUMERIC class test checks if a data item contains only numeric characters. The test is valid for USAGE DISPLAY, NATIONAL, COMP-3, and PACKED-DECIMAL.

Validating Domains with 88-Levels

When a field should only contain specific valid codes (like status flags), you can define 88-level condition names in the DATA DIVISION and use them in the PROCEDURE DIVISION to check if the data matches those expected values.

Predict the output cobol

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

       ID DIVISION. PROGRAM-ID. L88.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 COUNTER PIC 9 VALUE 0.
       01 ST PIC X VALUE "I".
          88 ACT VALUE "A".
          88 INA VALUE "I".
       PROCEDURE DIVISION.
           IF ACT ADD 5 TO COUNTER END-IF
           IF INA ADD 3 TO COUNTER END-IF
           DISPLAY COUNTER
           STOP RUN.
Output
3

Condition names are excellent for validating data against a domain of expected inputs without scattering literal values throughout the procedure division. By defining the states upfront, the compiler enforces clarity, and you never have to guess what “I” or “A” means in the middle of a complex routine.

Check yourself

Why is the IS NUMERIC test important before doing math in COBOL?

Reveal answer

Because COBOL math operations on non-numeric data usually cause program crashes (abends like S0C7). — COBOL variables hold raw memory. Math on garbage data causes data exceptions.

What does the INITIALIZE statement do?

Reveal answer

Sets numeric items to zeros and alphanumeric items to spaces. — INITIALIZE selectively clears fields based on their type, zeroing numeric fields and spacing out alphanumeric fields.

How does the NUMERIC class test handle signed fields (e.g., PIC S9)?

Reveal answer

It checks if the field contains a valid sign and valid digits. — For signed fields, IS NUMERIC validates both the representation of the sign and the digits.

Challenges

Challenge 1 +50 XP

Write a program that takes a 4-character input and displays 'MATH OK' if it is entirely numeric, or 'BAD DATA' if it contains letters.

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 (input: "12A4\n") — expects "BAD DATA\n"
Need a hint? (−25% XP)

Use the IS NUMERIC class condition in an IF statement.

Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. NumVal.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 RAW-INPUT PIC X(4).
PROCEDURE DIVISION.
    ACCEPT RAW-INPUT.
    IF RAW-INPUT IS NUMERIC
        DISPLAY "MATH OK"
    ELSE
        DISPLAY "BAD DATA"
    END-IF
    STOP RUN.

🐞 Bug Hunt +50 XP

Bug hunt: This program is supposed to display a cleared numeric field (0000) from the REC group, but it's displaying the leftover garbage value (9999). Fix the code by using the INITIALIZE statement to completely clear the REC group before the DISPLAY.

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 "0000\n"
Need a hint? (−25% XP)

Use the INITIALIZE statement on the group item.

Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. ClearRec.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 REC.
   05 NUM-1 PIC 9(4) VALUE 9999.
   05 STR-1 PIC X(3) VALUE "XYZ".
PROCEDURE DIVISION.
    INITIALIZE REC
    DISPLAY NUM-1
    STOP RUN.