IGZ0006S: Table reference outside the table (SSRANGE)
IGZ0006S means a COBOL program compiled with the SSRANGE option referred to a table element that lies outside the table, because a subscript or index held a value that was out of range. The runtime stops the program, and under Language Environment the step usually ends with abend U4038.
Other names for this code
Also written as IGZ0006, IGZ006S, IGZ0006S SSRANGE, IGZ0006S U4038, subscript out of range COBOL, addressed an area outside the region of the table.
What it means
A COBOL table is a fixed block of storage defined with OCCURS. When a statement uses a subscript or index, the program works out the address of that element from the start of the table. Nothing in the hardware stops that address from landing past the end of the table, or before its start.
The SSRANGE compile option adds code that checks each table reference when the statement runs. If the element it points to isn't inside the table, the COBOL runtime writes IGZ0006S and ends the program. The message names the table, the verb number and the source line number. A second line gives the compile unit and the offset in the program.
The S at the end means a severe error. Language Environment treats it as an unhandled condition and ends the step, usually with user abend U4038.
Without SSRANGE there is no check at all. The same bug then reads or overwrites whatever storage sits next to the table. That can give wrong results with no message, or a later S0C7 or S0C4 in a statement that has nothing to do with the table.
Enterprise COBOL 6.1 added suboptions. SSRANGE(ABD), the default, ends the program on the first failure. SSRANGE(MSG) writes a warning and lets the program carry on, so one test run can show every bad reference. IBM documents that the CHECK(OFF) runtime option doesn't turn these checks off in COBOL 6.
Common causes
- A loop that steps through the table runs one time too many, for example
PERFORM VARYING WS-IX FROM 1 BY 1 UNTIL WS-IX > 100on a table that only OCCURS 50 TIMES. - A subscript comes straight from input data, such as a branch or month number, and the record holds a value bigger than the table.
- The table grew in the data but not in the program. A file now has more entries than the OCCURS clause allows, and the load loop doesn't stop at the limit.
- Code relies on setting a subscript past the end on purpose to leave a loop. That works without SSRANGE and fails with it.
- A subscript field was never given a starting value, so it holds a leftover value from earlier processing.
How to find the problem
- Find IGZ0006S in the step's SYSOUT (or the CEEMSG output for the job). Note the table name and the line number it gives.
- Open the compile listing and go to that line. The verb number tells you which statement on the line failed, which matters when one line holds more than one statement.
- Look at every subscript and index used in that reference. A CEEDUMP shows their values if the program was compiled with TEST, which in Enterprise COBOL also lists WORKING-STORAGE in the dump.
- Compare the value with the OCCURS clause, and work back to where the subscript was last set.
How to fix it
- Correct the loop limit so it stops at the table size, ideally by testing against a constant or a count field rather than a hard-coded number.
- Check any subscript taken from input before you use it, and report or skip records with values out of range.
- Make the table bigger if the data really has outgrown it, and add a check in the load loop so the next overflow is reported cleanly.
- Use SEARCH with an AT END phrase where you are looking something up, so a missing entry doesn't run past the end.
- Keep SSRANGE on in test. In COBOL 6.1 and later, SSRANGE(MSG) lets one run show all the bad references before you fix them.
What it looks like
IGZ0006S The reference to table WS-RATE-ENTRY by verb number 01 on line 000412 addressed an area outside the region of the table.
From compile unit PAYCALC at entry point PAYCALC at compile unit offset +00000A3C at entry offset +00000A3C at address 1A400A3C.
IEF450I PAYRUN01 STEP020 - ABEND=S000 U4038 REASON=00000001IBM documentation
IBM z/OS documentation. Use the documentation for your installed release.
This link opens the relevant IBM reference library or lookup instructions. Match the complete code and your installed product release; it is not a code-specific review.
Related codes
Questions
Why does the program run without IGZ0006S in production but give wrong results?
Production is often compiled with NOSSRANGE, so nothing checks the subscript. The program quietly uses storage outside the table, which gives bad data or a later S0C7 or S0C4.
Can I make IGZ0006S a warning instead of an abend?
Yes, from Enterprise COBOL 6.1 with the service that added it. Compile with SSRANGE(MSG) and the program writes a warning for each bad reference and keeps running.
Does the CHECK(OFF) runtime option turn off SSRANGE?
Not in Enterprise COBOL 6. IBM documents that the range checks run whatever CHECK is set to, so to remove them you recompile without SSRANGE.