Chapter 20 Quiz: Debugging Techniques and Tools
Test your understanding of COBOL debugging concepts and techniques. Each question is followed by a hidden answer -- try to answer before revealing it.
Question 1
What is the simplest and most universally available debugging technique in COBOL?
Show Answer
The **DISPLAY** statement. It writes values to the system console (SYSOUT on z/OS, standard output on GnuCOBOL). Despite its simplicity, DISPLAY-based debugging is used extensively even by experienced programmers because it works in every COBOL environment, requires no special tools, and can be added to production programs with minimal risk. The key to effective DISPLAY debugging is strategic placement at decision points, before/after I/O operations, and at paragraph entry/exit.Question 2
What IBM z/OS abend code indicates a data exception -- attempting arithmetic on non-numeric data?
a) S0C1 b) S0C4 c) S0C7 d) S0CB
Show Answer
**c) S0C7**. This is the most common abend in COBOL programming. It occurs when a packed decimal or zoned decimal field contains invalid data (spaces, low-values, or other non-numeric characters) and the program attempts an arithmetic operation, numeric comparison, or numeric MOVE on it. The fix is to validate all numeric fields before using them in arithmetic and to initialize WORKING-STORAGE fields properly.Question 3
True or False: The READY TRACE statement causes the runtime to display the name of every paragraph and section as it is executed.
Show Answer
**True**. READY TRACE activates runtime tracing, which displays the name of each paragraph or section as the program enters it. RESET TRACE deactivates tracing. The output goes to SYSOUT (or standard output on GnuCOBOL). This is useful for understanding program flow but produces enormous output for large programs, so it should be used with caution and ideally limited to specific sections of code: READY TRACE
PERFORM 3000-SUSPECT-PARAGRAPH
RESET TRACE
Note: READY TRACE requires the COBOL compiler option TEST or the USE FOR DEBUGGING declarative in some implementations.
Question 4
What section of the IBM COBOL compiler listing shows the hexadecimal displacement of each data item from the start of its base locator?
Show Answer
The **Data Division Map** (generated by the MAP compiler option). This listing shows each data item's level number, name, base locator (BLF for File Section, BLW for Working-Storage, BLL for Linkage Section), displacement in hexadecimal, definition, and usage (DISPLAY, COMP, COMP-3, etc.). The Data Division Map is essential for dump analysis because it allows you to locate the exact memory position of any data item.Question 5
Which compiler option generates runtime checking for subscript and index out-of-range conditions?
Show Answer
**SSRANGE** (Subscript/Index Range checking). When SSRANGE is active, the runtime system checks every subscript, index, and reference modification to ensure it falls within the defined bounds. If a violation is detected, the program abends with a diagnostic message identifying the failing statement and the out-of-range value. SSRANGE should be **on during development and testing** and **off in production** (it adds approximately 5-10% overhead). The production alternative is to validate subscript values in the application logic before using them.Question 6
What does abend code S0C4 indicate?
Show Answer
**S0C4** is a **protection exception** (also called an addressing exception). It occurs when a program tries to access a memory address that is not allocated to it, or that is protected. Common causes in COBOL include: - Subscript or index wildly out of range (pointing into unallocated memory) - Incorrect LINKAGE SECTION mapping (the called program's LINKAGE SECTION is larger than the data passed by the caller) - Using an uninitialized pointer or address - A previous WORKING-STORAGE overlay that corrupted a subscript or pointer value - Running out of WORKING-STORAGE due to insufficient REGION size Unlike S0C7 (which points to a specific numeric field), S0C4 can be difficult to diagnose because the corrupted address may have been set far from the point of failure.Question 7
True or False: The COBOL compiler's cross-reference listing (XREF option) shows every place in the program where each data name is referenced and whether it was modified.
Show Answer
**True**. The cross-reference listing shows each identifier, the line where it is defined, and every line where it is referenced. References where the identifier is modified (receiving field in a MOVE, target of an arithmetic operation, etc.) are marked with an **M** prefix. This is invaluable for debugging because it lets you quickly find: - Variables that are defined but never referenced (possible copy/paste error) - Variables that are referenced but never modified (may be uninitialized) - All places where a suspect variable is changed (to trace a bad value to its source)Question 8
In a z/OS dump, what does the PSW (Program Status Word) tell you about an abend?
Show Answer
The **PSW** contains the address of the instruction that was being executed (or was about to be executed) when the abend occurred. To find the failing source line: 1. Extract the instruction address from the PSW 2. Find the program's load point (Entry Point Address, or EPA) from the dump header 3. Subtract the EPA from the PSW address to get the **offset** within the program 4. Look up this offset in the compiler's **OFFSET** listing or **LIST** (assembler) listing to find the corresponding COBOL source line For example: PSW address = X'00045A2E', EPA = X'00044000'. Offset = X'00045A2E' - X'00044000' = X'00001A2E'. Find offset 1A2E in the compiler listing to identify the failing statement.Question 9
What GnuCOBOL environment variable activates runtime tracing?
Show Answer
**COB_SET_TRACE** (set to "Y") activates runtime tracing in GnuCOBOL. Other important GnuCOBOL debugging environment variables include: | Variable | Purpose | |----------|---------| | COB_SET_TRACE | Activates paragraph/section tracing | | COB_TRACE_FILE | Redirects trace output to a file | | COB_STACK_SIZE | Sets the PERFORM stack size | | COB_RUNTIME_WARNINGS | Enables runtime warning messages | To set up tracing on Linux:export COB_SET_TRACE=Y
export COB_TRACE_FILE=/tmp/cobol-trace.log
./my-program
Question 10
What is the difference between the LIST and OFFSET compiler options?
Show Answer
- **LIST** generates a full **assembler language expansion** of the COBOL source code. Each COBOL statement is shown with the machine instructions it generated, including hex offsets. This is the most detailed listing and is needed for complex dump analysis. - **OFFSET** generates a condensed listing showing only the **hex offset of the first instruction** generated for each COBOL verb in the Procedure Division. It is much shorter than LIST and is sufficient for most dump analysis (mapping an abend offset to a source line). For routine debugging, OFFSET is preferred because it is smaller and easier to navigate. LIST is needed when you must examine the generated code to understand data movement, field alignment, or optimization behavior.Question 11
What IBM tool provides interactive step-through debugging for COBOL programs on z/OS?
Show Answer
**IBM Debug Tool** (now called **IBM z/OS Debugger**, part of IBM Developer for z/OS). It allows you to: - Set breakpoints at specific lines or paragraphs - Step through execution one statement at a time - Inspect and modify variable values during execution - Set conditional breakpoints (break only when a variable equals a specific value) - Monitor variables for changes - Debug batch programs, CICS transactions, and DB2 stored procedures The program must be compiled with the **TEST** compiler option to use the debugger. The debugger can run in full-screen mode (3270 terminal), in a remote GUI (IBM Developer for z/OS on a workstation), or in batch mode using a commands file.Question 12
True or False: You can use the IBM Debug Tool to debug a production program without recompiling it.
Show Answer
**It depends**. If the program was originally compiled with the **TEST** option (or TEST(SEPARATE)), the debug information is available and no recompile is needed. Many shops compile production programs with TEST(SEPARATE,SOURCE) to make debugging possible without embedding test hooks in the production load module. If the program was compiled without TEST, you must recompile with TEST enabled. However, you can sometimes still use the **OFFSET** listing and a dump to perform post-mortem analysis without the debugger. Some newer versions of the z/OS Debugger also support **TEST(NOSEPARATE,NOEJPD)** which embeds minimal debug information with lower overhead, suitable for production use.Question 13
What abend code indicates that a CALL statement could not find the target program?
Show Answer
**S806** (module not found). This occurs when a CALL statement specifies a program name that cannot be found in any of the load library concatenations (STEPLIB, JOBLIB, or system link list). Common causes: - Misspelled program name in the CALL statement - Program not compiled/linked into the expected load library - Missing STEPLIB DD in the JCL - Program name is in a variable that contains unexpected characters (trailing spaces in a CALL identifier) The fix is to verify the program name, check that the load module exists in the correct library, and ensure the library is in the STEPLIB concatenation.Question 14
What is a "condensed listing" in an IBM COBOL compilation?
Show Answer
A **condensed listing** (compiler option FLAG) shows only the lines that received diagnostic messages (errors, warnings, informational messages). It suppresses all error-free lines. This is useful when compiling large programs where you only want to see the problems. The FLAG option has sub-parameters that control the minimum severity level: - **FLAG(I)** -- show all messages (Informational and above) - **FLAG(W)** -- show Warnings and above - **FLAG(E)** -- show Errors and above - **FLAG(S)** -- show only Severe errors In practice, FLAG(W) is the most common setting: it suppresses informational messages but shows all potential problems.Question 15
How do you debug a numeric truncation issue where cents are being dropped from financial amounts?
Show Answer
Numeric truncation in COBOL can occur in several ways: 1. **PIC clause mismatch**: Moving PIC S9(7)V99 to PIC S9(7) drops the decimal places. 2. **Group MOVE**: A group MOVE treats the source as alphanumeric, losing the implied decimal position. 3. **Missing ROUNDED**: COMPUTE without ROUNDED truncates rather than rounding. 4. **Integer intermediate result**: `DIVIDE A BY B GIVING C` where C has no decimal places. 5. **DISPLAY field receiving COMP-3**: The receiving field's PIC determines precision. Debugging approach: 1. Add DISPLAY statements showing the field value at each step from input to output 2. Check the PIC clauses of every field in the calculation chain using the Data Division Map 3. Look for group MOVEs that involve numeric fields 4. Check for CORRESPONDING moves or INITIALIZE that might reset decimal portions 5. Verify that intermediate calculation fields have sufficient decimal precisionQuestion 16
What is the purpose of the WITH DEBUGGING MODE clause in the ENVIRONMENT DIVISION?
Show Answer
The **WITH DEBUGGING MODE** clause (coded in the SOURCE-COMPUTER paragraph) activates debugging lines in the source code. Debugging lines are source lines that have a **D** in column 7 (indicator area): SOURCE-COMPUTER. IBM-370 WITH DEBUGGING MODE.
...
PROCEDURE DIVISION.
1000-PROCESS.
D DISPLAY 'ENTERING 1000-PROCESS'
D DISPLAY 'AMOUNT = ' WS-AMOUNT
COMPUTE WS-RESULT = WS-AMOUNT * WS-RATE
D DISPLAY 'RESULT = ' WS-RESULT
.
When WITH DEBUGGING MODE is specified, lines with D in column 7 are compiled as normal statements. When the clause is removed, those lines are treated as comments. This provides a compile-time switch for debug code without needing to physically remove and re-add DISPLAY statements.
Question 17
True or False: The SSRANGE compiler option can detect a reference modification that extends beyond the end of a data item.
Show Answer
**True**. SSRANGE checks three types of bounds violations: 1. **Subscripts**: OCCURS table subscripts that exceed the defined range 2. **Indexes**: SET-based indexes that point beyond the table 3. **Reference modification**: Starting position or length that would access bytes beyond the end of the data item For example, if WS-NAME is PIC X(20) and the program executes `MOVE WS-NAME(18:5)`, SSRANGE would detect that the reference modification tries to access bytes 18-22, but the field only has bytes 1-20. Without SSRANGE, this would silently read adjacent memory, potentially causing incorrect results or an eventual S0C4.Question 18
What is the relationship between the COBOL RETURN-CODE special register and the JCL COND parameter?
Show Answer
The **RETURN-CODE** special register contains the value that is passed back to the operating system (or the calling program) when the COBOL program terminates. In JCL, the **COND** parameter on the EXEC statement tests this return code to decide whether to execute subsequent steps: * In the COBOL program:
MOVE 8 TO RETURN-CODE
STOP RUN
//STEP02 EXEC PGM=NEXTPROG,COND=(8,LT)
The COND parameter syntax is `COND=(value,operator)`, but it specifies when to **skip** the step (confusingly). `COND=(8,LT)` means "skip this step if 8 is Less Than the return code" -- i.e., skip if the return code is greater than 8.
The IF/THEN/ELSE/ENDIF construct in JCL provides a more readable alternative:
// IF (STEP01.RC <= 4) THEN
//STEP02 EXEC PGM=NEXTPROG
// ENDIF
Convention: RC=0 is success, RC=4 is warning, RC=8 is error, RC=16 is severe error.
Question 19
How do you compile a GnuCOBOL program with debugging enabled?
Show Answer
Use the **-g** flag (include debug information) and optionally **-debug** (enable runtime checks) or **-fdebugging-line** (compile D-lines):# Basic debug compilation
cobc -x -g -debug loan-calc.cbl -o loan-calc
# With debugging lines (D in column 7) enabled
cobc -x -g -debug -fdebugging-line loan-calc.cbl -o loan-calc
# With additional runtime checks
cobc -x -g -debug -fbounds-check loan-calc.cbl -o loan-calc
To run under GDB (GNU Debugger):
gdb ./loan-calc
(gdb) break 3000-CALCULATE-INTEREST
(gdb) run
(gdb) print WS-AMOUNT
(gdb) next
(gdb) continue
The **-g** flag generates debug symbols that GDB can use. The **-debug** flag enables COBOL-specific runtime checking similar to IBM's SSRANGE.
Question 20
What is the difference between a system abend (Sxxx) and a user abend (Uxxx)?
Show Answer
- **System abends (Sxxx)**: Generated by the operating system or hardware. The program violated a system-level rule (invalid memory access, invalid instruction, timeout). Examples: S0C7 (data exception), S0C4 (protection exception), S322 (CPU time exceeded), S806 (module not found). - **User abends (Uxxx)**: Generated by the application program itself or by its runtime environment. The COBOL runtime issues user abends for conditions it detects. Examples: U4038 (general COBOL runtime error), U4036 (sort error), U1026 (LE condition handler). A COBOL program can explicitly issue a user abend: CALL 'CEE3ABD' USING WS-ABEND-CODE
WS-CLEANUP-FLAG
Or using the older:
CALL 'ILBOABN0' USING WS-ABEND-CODE
User abends are typically more informative because they come with accompanying messages in SYSOUT.
Question 21
What technique would you use to find a performance bottleneck in a COBOL batch program?
Show Answer
**Timestamp-based profiling** using DISPLAY and FUNCTION CURRENT-DATE: 01 WS-TIME-START PIC X(21).
01 WS-TIME-END PIC X(21).
MOVE FUNCTION CURRENT-DATE TO WS-TIME-START
PERFORM 3000-HEAVY-PROCESSING
MOVE FUNCTION CURRENT-DATE TO WS-TIME-END
DISPLAY 'PARA 3000: START=' WS-TIME-START(9:12)
' END=' WS-TIME-END(9:12)
Additional techniques:
1. **SMF Type 30 records**: Show CPU time, I/O counts, and elapsed time per step
2. **RMF (Resource Measurement Facility)**: Shows system-level I/O wait times and contention
3. **IBM Application Performance Analyzer**: Profiles COBOL programs at the statement level
4. **DFSORT statistics**: Show sort performance metrics (memory used, merge passes)
The most common bottleneck in COBOL batch is **I/O**: check BLKSIZE (larger blocks = fewer I/Os), BUFNO (more buffers = better overlap), and dataset placement (fragmented datasets cause excessive arm movement).
Question 22
What is a COBOL "snap dump" and when would you use one?
Show Answer
A **snap dump** is a snapshot of selected portions of memory at a specific point during program execution, without terminating the program. Unlike an abend dump (which occurs at failure), a snap dump is deliberately triggered by the programmer to capture the state of the program while it continues running. In IBM COBOL, you can produce a snap dump by calling the Language Environment service: CALL 'CEE3DMP'
USING WS-DUMP-TITLE
WS-DUMP-OPTIONS
WS-FEEDBACK-CODE
Or using the older COBOL approach with the EXHIBIT statement (where supported):
Snap dumps are useful when:
- You need to see the state of data at multiple points during a long run
- The problem is intermittent and you want to capture data without stopping
- You want to compare data values at two different stages of processing
- An abend dump does not provide enough context because the error is far from the symptom
Question 23
True or False: The IBM COBOL compiler option TEST(SEPARATE) stores debug information in a separate file rather than embedding it in the load module.
Show Answer
**True**. TEST(SEPARATE) directs the compiler to write debug information (source listings, variable mappings) to a separate **SYSDEBUG** file rather than embedding it in the object module. This has two benefits: 1. **Smaller production load modules**: The load module is the same size as a non-TEST compilation, so there is no performance overhead in production. 2. **Debug when needed**: When debugging is required, the debugger reads the separate debug file. When not debugging, the file is not accessed. The SYSDEBUG file is typically stored as a PDS member in a debug information library. The debugger locates it through a EQADEBUG DD or session settings.Question 24
What should you check first when a COBOL program produces incorrect output but no abend?
Show Answer
When a program produces incorrect output without abending, check the following in order: 1. **RETURN-CODE and file status values**: Even without an abend, I/O errors may have occurred silently if file status is not checked. 2. **Record counts**: Compare input record count to output record count. Missing records indicate a logic error in the read loop or a filtering condition that is too aggressive. 3. **Control totals**: Compare accumulated totals to expected values. A discrepancy narrows the problem to a specific calculation. 4. **Boundary conditions**: Check the first record, last record, and records at control breaks. Off-by-one errors often affect boundaries. 5. **Data flow**: DISPLAY the key fields at each transformation step -- from input, through validation, calculation, and output -- to find where the values diverge from expectations. 6. **Logic paths**: Verify that EVALUATE and IF statements are directing records to the correct processing paths. An incorrect condition can silently route records to the wrong paragraph.Question 25
What is the S322 abend and how do you resolve it?