Showing posts with label COBOL debugging. Show all posts
Showing posts with label COBOL debugging. Show all posts

Sunday, 11 August 2013

COBOL SSRANGE Compiler Option: Find Table Bounds Errors

A COBOL table with OCCURS 50 TIMES will not protect itself when a bad subscript tries to read occurrence 51. The SSRANGE compiler option tells Enterprise COBOL to generate runtime checks for table references and reference modification, so these errors are found before they quietly damage nearby storage.

COBOL SSRANGE compiler option diagram showing table OCCURS, range checking, and MSG or ABEND result
Catch bad table references.

What is the COBOL SSRANGE compiler option?

SSRANGE generates code that checks whether subscripts, indexes, ALL subscripts, variable-length references, and reference modification expressions point outside the valid storage area. IBM documents the default as NOSSRANGE.

If SSRANGE is coded without suboptions, IBM treats it as SSRANGE(NOZLEN,ABD). That means zero-length reference modification is treated as an error, and the first detected range problem causes a runtime error and abend.

SSRANGE vs NOSSRANGE

Option Runtime behavior Good fit
NOSSRANGE No generated range-check code for the covered references. Production programs where performance matters and range logic has already been tested.
SSRANGE Generated code checks covered table, index, and reference modification use. Unit test, system test, migration test, and programs with suspected storage overlay.

Table range example

This table allows 50 entries. If WS-SUB becomes 51, the program is trying to address storage outside the table. With SSRANGE, Enterprise COBOL can catch that bad reference at run time.

01 WS-CUSTOMER-TABLE.
   05 WS-CUSTOMER-ENTRY OCCURS 50 TIMES.
      10 WS-CUSTOMER-ID     PIC X(10).
      10 WS-CUSTOMER-BAL    PIC S9(7)V99 COMP-3.

01 WS-SUB                   PIC S9(4) COMP.

MOVE 51 TO WS-SUB
DISPLAY WS-CUSTOMER-ID(WS-SUB)

Without a range check, the display might read some unrelated field after the table. That kind of failure is painful because the abend may happen much later than the bad reference.

Reference modification checks

SSRANGE also checks reference modification for non-UTF-8 data items and function values. IBM documents checks for starting position, current length, ending position, and length value.

01 WS-NAME                  PIC X(20).
01 WS-START                 PIC S9(4) COMP.
01 WS-LEN                   PIC S9(4) COMP.

MOVE 18 TO WS-START
MOVE 5  TO WS-LEN
DISPLAY WS-NAME(WS-START:WS-LEN)

In this example, positions 18 through 22 are requested from a 20-byte field. That should be fixed in logic, not hidden by hoping the next bytes happen to be harmless.

MSG and ABD suboptions

The MSG and ABD suboptions control what happens after a range check fails. Use ABD when the first bad reference should stop the program. Use MSG during migration or wider testing when you want warning messages and continued execution so more range problems can be found in one run.

CBL SSRANGE(MSG)

* or

CBL SSRANGE(ABD)

MSG is useful for discovery, but do not treat a warning-only run as clean production behavior. A bad subscript still needs a code fix.

ZLEN and NOZLEN suboptions

ZLEN and NOZLEN control zero-length reference modification. With ZLEN, a zero length is allowed. With NOZLEN, a zero length gets an SSRANGE error. IBM documents NOZLEN as the compatible behavior with older SSRANGE handling.

CBL SSRANGE(ZLEN,MSG)
CBL SSRANGE(NOZLEN,ABD)

Pick the setting that matches your compiler level and site migration rule. The point is not to make the compile option look tidy; it is to catch the reference rules your application must obey.

Performance impact

SSRANGE adds generated checks to many references. IBM performance guidance recommends NOSSRANGE for best performance and notes that range checking can slow programs that use subscripts, indexes, and reference modification in performance-sensitive paths.

IBM also documents that in COBOL 6 the compiled-in checks are always conducted at run time. You cannot compile with SSRANGE and then turn those checks off later by specifying CHECK(OFF).

When to use SSRANGE

  • Use it during unit test for programs with new or changed tables.
  • Use it when a storage overlay points to bad subscript logic.
  • Use it during compiler migration testing.
  • Use it for a focused diagnostic compile when production data exposes a rare table problem.

When to avoid SSRANGE

Avoid leaving SSRANGE on blindly for call-heavy, table-heavy, or high-volume batch programs unless the site has chosen that tradeoff. If only a few references need checking, a local bounds check around those references can be faster and easier to explain.

IF WS-SUB >= 1 AND WS-SUB <= 50
   DISPLAY WS-CUSTOMER-ID(WS-SUB)
ELSE
   DISPLAY 'BAD CUSTOMER SUBSCRIPT: ' WS-SUB
END-IF

Local checks are also useful when the program should handle bad input gracefully instead of abending on the first bad table reference.

Common mistakes

Thinking SSRANGE checks the subscript value itself

IBM explains that each subscript or index is not individually checked for validity. The effective address is checked to make sure it does not reference outside the table area.

Expecting CHECK(OFF) to disable COBOL 6 SSRANGE checks

For COBOL 6, compiled-in SSRANGE checks remain active at run time. Plan the compile option deliberately.

Using NOSSRANGE to hide a real bug

NOSSRANGE can reduce overhead, but it does not make bad table logic correct. Fix the subscript or reference modification rule first.

Related Mainframe Forum guides

For nearby topics, read COBOL USAGE clause, COBOL ARITH compiler option, COBOL TRUNC compiler option, COBOL fixed vs variable-length records, and COBOL performance tuning.

External references

IBM documents the SSRANGE compiler option, SSRANGE performance guidance, and the related MSG and ABD suboption APAR.

FAQ

What does SSRANGE do in COBOL?

SSRANGE generates runtime checks for out-of-range table references, indexes, subscripts, variable-length references, and reference modification expressions.

What is the default for SSRANGE?

IBM documents the default as NOSSRANGE.

Should SSRANGE be used in production?

Many sites use SSRANGE mainly in test because it adds runtime checks. Production use depends on the program risk, performance cost, and site standards.

Can CHECK(OFF) disable SSRANGE in COBOL 6?

No. IBM documents that COBOL 6 compiled-in SSRANGE checks are always conducted at run time.

COBOL TEST Compiler Option: Debug Builds on z/OS

A COBOL abend in test is much easier to fix when the debugger can show the failing statement and variable names. The TEST compiler option tells Enterprise COBOL to create debug information for tools such as IBM z/OS Debugger. NOTEST is the normal choice when a release build does not need that debug data.

COBOL TEST compiler option diagram showing source lines, DWARF symbols, and z/OS Debugger
Build with debug data.

What is the COBOL TEST compiler option?

TEST controls the debug information produced by the COBOL compiler. IBM describes it as the option used to create the information needed to debug a program, including where that information is placed.

The exact suboptions depend on the compiler level. Enterprise COBOL 6.2 and later support modern combinations such as TEST(SEPARATE,SOURCE,EJPD) and NOTEST(DWARF,SOURCE). Older compilers used other forms, so always check the compile listing for the actual options in effect.

TEST vs NOTEST

Option Meaning Typical use
TEST Produces debug data for source-level debugging. Unit test, system test, problem recreation, and controlled support builds.
NOTEST Does not request full source-level debug support. Normal production builds when source debugging is not required.

Common TEST suboptions

SOURCE and NOSOURCE

SOURCE keeps source information available for the debugger. Use it when a developer needs to step through COBOL statements rather than only inspect offsets or dumps.

SEPARATE and NOSEPARATE

SEPARATE can place debug information outside the main program object for supported compiler levels. That can reduce object size while keeping source-level debugging available, but the separate debug file must be cataloged and available during the debug session.

DWARF and NODWARF

Modern Enterprise COBOL can use DWARF debug information. IBM notes that newer NOTEST combinations can still include DWARF data for tools that use it, depending on the compiler level and selected suboptions.

EJPD and NOEJPD

EJPD supports some debugger actions such as predictable variable changes and certain jump commands when used with selected optimization options. It can affect generated code, so use it only when the debug scenario needs it.

Example compile options

This example shows the intent, not a site standard. Your compile PROC might pass options through a symbolic parameter such as PARM.COBOL.

//COBOL  EXEC PGM=IGYCRCTL,
//             PARM='TEST(SEPARATE,SOURCE,EJPD),LIST,MAP,XREF'
//SYSIN  DD  DSN=DEV.COBOL.SOURCE(ACCT001),DISP=SHR
//SYSLIN DD  DSN=&&OBJ,DISP=(MOD,PASS),UNIT=SYSDA,
//             SPACE=(CYL,(1,1))

For a normal release build, the same site might use NOTEST with the other production compiler options approved by the build team.

When to use TEST

  • Use TEST when a developer must debug statement-by-statement in a controlled test environment.
  • Use it when a recurring abend needs source lines and variable names to shorten the investigation.
  • Use it for support builds only when the debug data is stored and secured according to site rules.
  • Use NOTEST when the program is being built for a normal production release and debug data is not required.

Production checks

Do not move a debug build to production just because it passed a test cycle. Check the compile listing, binder listing, load library, and deployment package. If your release process stores debug files separately, confirm they are not lost before a support team needs them.

For online programs, confirm the runtime and debugger setup with the CICS, IMS, or batch support team. A compile option alone does not make every runtime debugging scenario available.

Common mistakes

Assuming TEST is active from the PROC name

A PROC named COBTEST can still pass NOTEST after symbolic substitution. Read the compiler listing to see the final option set.

Losing the separate debug file

If the build uses a separate debug file, keep it cataloged, backed up, and tied to the exact program object. A mismatched debug file can waste hours during an abend call.

Mixing old and new compiler guidance

Enterprise COBOL V3, V4, V5, and V6 do not all use the same TEST suboption rules. Use the documentation for the compiler level shown in the compile listing.

Review checklist

  • Confirm the compiler version and maintenance level.
  • Check whether the build uses TEST or NOTEST.
  • Check whether SOURCE, SEPARATE, DWARF, or EJPD is needed.
  • Confirm the debug file location when SEPARATE is used.
  • Keep debug data under the same access controls as source and load modules.
  • Rebuild after changing compiler options; do not rely on an old load module.

Related Mainframe Forum guides

For nearby topics, read COBOL program compilation process, COBOL SSRANGE compiler option, COBOL RENT compiler option, COBOL ARITH compiler option, COBOL DYNAM compiler option, and COBOL file status.

External references

IBM documents choosing TEST and NOTEST suboptions, compiling with Enterprise COBOL, and compiler option changes in Enterprise COBOL 5 and 6.

FAQ

What does TEST do in COBOL?

TEST tells the compiler to produce debug information that can be used by source-level debugging tools.

Should TEST be used in production?

Usually no. Use production compiler options approved by your build team. Keep TEST for controlled debug and support builds unless your site standard says otherwise.

What is TEST(SEPARATE)?

TEST(SEPARATE) stores supported debug information separately from the main program object, depending on the compiler level and selected suboptions.

What should I check first when debugging does not work?

Read the compile listing. Confirm the compiler version, final TEST or NOTEST option, source suboption, and debug file location.

COBOL INITIAL Compiler Option: Reset Working-Storage

A called COBOL subprogram can remember values in WORKING-STORAGE from the previous call. That is useful for a counter or cached lookup, but it is dangerous when the next call expects a clean start. The INITIAL compiler option changes that behavior by treating programs as if IS INITIAL was coded on PROGRAM-ID.

COBOL INITIAL compiler option diagram showing a CALL, initial state, and VALUE fields
Reset only when needed.

What is the COBOL INITIAL compiler option?

INITIAL causes a program and its nested programs to behave as if the IS INITIAL clause was specified on the PROGRAM-ID paragraph. IBM documents NOINITIAL as the default.

The option is useful when a subprogram must start in the same state each time it is entered. It should not be used as a blanket substitute for clear program initialization logic.

INITIAL vs NOINITIAL

Option Behavior Common fit
INITIAL Treats the program as initially called each time it is entered. Subprograms that must not retain prior call values.
NOINITIAL Leaves normal source behavior in place. Most production programs unless the design needs automatic reset.

PROGRAM-ID IS INITIAL example

The compiler option applies the same idea as coding IS INITIAL in the source. This short example shows the source-level form.

IDENTIFICATION DIVISION.
PROGRAM-ID. ACCTEDIT IS INITIAL.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-ERROR-COUNT      PIC 9(04) VALUE ZERO.
01 WS-LAST-FIELD       PIC X(20) VALUE SPACES.

When ACCTEDIT is entered again, the VALUE clauses are used to place those fields back into their starting values.

What happens to WORKING-STORAGE?

IBM documents that WORKING-STORAGE data items normally persist in their last-used state for the duration of the run unit. When a program has INITIAL behavior, WORKING-STORAGE data items are reinitialized each time the program is entered.

There is one important boundary: IBM also notes that INITIAL and IS INITIAL do not affect data items that do not have VALUE clauses. Do not assume every field becomes spaces or zero unless the definition says so.

WORKING-STORAGE vs LOCAL-STORAGE

LOCAL-STORAGE is already allocated for each call or method invocation and freed on return. If a LOCAL-STORAGE item has a VALUE clause, it is initialized on each call. That makes LOCAL-STORAGE a better fit for many temporary fields.

Use INITIAL when the program-level reset behavior is part of the design. Use explicit initialization or LOCAL-STORAGE when only a few fields need fresh values.

When to use INITIAL

  • Use it for a subprogram that must not remember values between calls.
  • Use it when old accumulator, flag, or error fields have caused repeat-call defects.
  • Use it when nested programs also need initial-call behavior.
  • Use source-level IS INITIAL when only one program should behave that way.

When to avoid INITIAL

Avoid INITIAL when retained state is part of the program design. Some subprograms intentionally keep lookup data, counters, or previous-call information in WORKING-STORAGE. Resetting those fields can create wrong results or extra CPU work.

The old version of this post mentioned heavy call overhead in a very small benchmark. Treat that as a warning, not a universal number. Measure your real program if it calls a subprogram many times and the subprogram has large WORKING-STORAGE.

INITIAL, CANCEL, and dynamic CALL

A dynamically called subprogram can be reset after a CANCEL, because it is loaded again on a later call. INITIAL is different: it applies the initial-state behavior each time the program is entered, without depending on a caller issuing CANCEL.

Do not add CANCEL only to clear data if your site avoids it for performance or program-management reasons. Pick the reset method deliberately.

Common mistakes

Expecting fields without VALUE clauses to reset

INITIAL does not make an undefined field clean by magic. Code VALUE clauses or explicit initialization for fields that need known starting values.

Using INITIAL across every compile

A site-wide compiler option can change behavior in many subprograms at once. Review retained-state programs before changing a compile PROC default.

Ignoring nested programs

IBM documents that INITIAL applies to the program and its nested programs. Check nested routines when a reset changes more than expected.

Review checklist

  • Check whether the source already has PROGRAM-ID ... IS INITIAL.
  • Confirm whether the compile listing shows INITIAL or NOINITIAL.
  • List which WORKING-STORAGE fields are expected to retain values.
  • Add VALUE clauses or explicit initialization where fields need known values.
  • Measure call-heavy code before changing reset behavior in a hot path.
  • Retest callers that rely on repeat-call state.

Related Mainframe Forum guides

For nearby topics, read COBOL DYNAM compiler option, COBOL RENT compiler option, COBOL THREAD compiler option, COBOL USAGE clauses, COBOL INITIALIZE statement, and COBOL CALL statement.

External references

IBM documents the INITIAL compiler option, WORKING-STORAGE and LOCAL-STORAGE behavior, and Enterprise COBOL compiler options.

FAQ

What does the COBOL INITIAL compiler option do?

INITIAL makes the program and nested programs behave as if IS INITIAL was coded on PROGRAM-ID.

Is NOINITIAL the default?

Yes. IBM documents NOINITIAL as the default for the Enterprise COBOL INITIAL option.

Does INITIAL reset every WORKING-STORAGE item?

No. INITIAL does not affect data items that do not have VALUE clauses, so fields needing known values still need clear definitions or explicit initialization.

Should INITIAL be used for performance tuning?

No. Use INITIAL for correct reset behavior. If performance is a concern, measure the actual call path and storage size.

New In-feed ads