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

Sunday, 22 September 2013

COBOL Working Storage vs Local Storage: Key Differences

COBOL Working Storage vs Local Storage comparison showing persistent values and fresh copy per call
Working Storage keeps state; Local Storage starts fresh for each call.

A COBOL subprogram can return cleanly on the first call and fail on the second because a counter, switch, or table entry kept its old value in WORKING-STORAGE. Move the same item to LOCAL-STORAGE, and COBOL allocates a fresh copy for each call. That is the practical difference developers need before debugging a strange rerun or CALL problem.

Short rule: Working Storage persists for the run unit unless the program is initialised again. Local Storage is allocated for each invocation and freed when the program returns.

Working Storage vs Local Storage Comparison

Question Working Storage Local Storage
Scope Visible to the program that defines it. Visible to the program or method invocation that defines it.
Initialisation VALUE clauses are applied when the run unit starts, or when the program is reinitialised after CANCEL or INITIAL. VALUE clauses are applied on each call or method invocation. Without VALUE, the initial content is undefined.
Persistence between CALL statements Usually keeps the last-used value between calls in the same run unit. Does not keep values after return. A new copy is allocated for the next invocation.
When to use Use for program-level state that must remain available across paragraphs or repeated calls. Use for temporary work fields that should start fresh for each call, especially in reusable subprograms.

What Working Storage Means in COBOL

WORKING-STORAGE SECTION is part of the COBOL Data Division. It defines fields that belong to the program and remain available while the program is active in the run unit. A batch driver that calls the same subprogram many times can therefore see old values if the subprogram keeps counters, switches, or save areas in Working Storage and does not reset them.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CALL-COUNT        PIC 9(4) VALUE ZERO.
01 WS-LAST-CUSTOMER     PIC X(10).

PROCEDURE DIVISION.
    ADD 1 TO WS-CALL-COUNT
    DISPLAY 'CALL COUNT=' WS-CALL-COUNT
    GOBACK.

If this program is called three times in the same run unit, WS-CALL-COUNT can show 1, then 2, then 3. That is useful when the program intentionally tracks state. It is a bug when the field was meant to be temporary.

What Local Storage Means in COBOL

LOCAL-STORAGE SECTION defines fields that are allocated when the program or method is invoked and freed when it returns. This makes Local Storage a good fit for scratch variables in reusable routines, recursive-style logic, and programs that may run in multiple invocations.

DATA DIVISION.
LOCAL-STORAGE SECTION.
01 LS-ITEM-AMOUNT       PIC 9(5) VALUE ZERO.
01 LS-WORK-FLAG         PIC X    VALUE 'N'.

PROCEDURE DIVISION.
    MOVE 'Y' TO LS-WORK-FLAG
    GOBACK.

On the next call, LS-WORK-FLAG is allocated again and the VALUE clause is applied again. That behavior is often safer for work fields that should not remember a previous transaction, customer, or input record.

CALL Behavior That Causes Runtime Errors

The easiest trap is a subprogram called repeatedly from a driver. A field in Working Storage keeps its last value, so a flag that should start as N might still be Y. A table index might still point past the last loaded entry. A previous customer number might leak into the next calculation.

Use Working Storage when that persistence is intentional. Use Local Storage when each call should start with a clean set of work fields. If a program uses PROGRAM-ID. name IS INITIAL, or if the caller issues CANCEL before calling again, Working Storage can be reinitialised, but that is a program-control decision and should not be hidden inside a variable naming habit.

Threading Difference

In environments where the same program can run in multiple simultaneous invocations, Working Storage can be shared by those invocations, while Local Storage gives each invocation a separate copy. That difference matters in CICS and other multi-tasking designs. If a field belongs to one transaction, request, or invocation, Local Storage is usually the safer place.

Where This Fits in the Data Division

Both sections belong to the COBOL Data Division, along with File Section and Linkage Section. For a broader layout of the Data Division, see the COBOL Data Division guide. If your bug is about fields passed between a caller and subprogram, also review the COBOL CALL statement and parameter passing guide.

Common Mistakes

  • Putting a temporary transaction flag in Working Storage and forgetting to reset it before every call.
  • Assuming Local Storage keeps a value after GOBACK.
  • Using VALUE clauses as a substitute for explicit reset logic in a long-running program.
  • Treating CANCEL as harmless when the called program relies on Working Storage persistence.

Practical Rule

If the value must survive the next call, use Working Storage and reset it deliberately when needed. If the value belongs only to this invocation, use Local Storage so old data cannot sneak into the next run path.

COBOL Application Structure: Main Program, Subprograms, and Run Unit

A payroll batch job rarely has only one COBOL program. One program reads the employee file, another validates pay codes, another calculates deductions, and a final report step prints totals for payroll control. Together, those programs form the COBOL application that the batch job runs.

COBOL application structure diagram with main program subprograms files DB2 and reports
Keep the modules clear.

What is a COBOL application?

A COBOL application is a group of programs, files, screens, database calls, reports, and job steps that work together to complete one business task. The task can be payroll, policy renewal, account posting, claim processing, statement printing, or a month-end batch process.

The old version of this page used an employee management example. That is still a useful way to picture the idea: employee registration, salary calculation, daily requests, and reporting can be separate modules in one application. Each module has a smaller job, but the application owns the full business result.

COBOL application versus COBOL program

A COBOL program is one compiled source member with divisions such as IDENTIFICATION DIVISION, ENVIRONMENT DIVISION, DATA DIVISION, and PROCEDURE DIVISION. A COBOL application is bigger than one program. It can include many COBOL programs and can also call programs written in other Language Environment member languages.

Item Meaning Example
Program One COBOL source member that is compiled. PAYMAIN, PAYCALC, PAYRPT
Application A set of programs and resources that complete a business process. Payroll processing for one pay cycle
Run unit One or more object programs that work together at run time. PAYMAIN calling PAYCALC and TAXCALC

Main program and subprograms

IBM describes the first COBOL program in a run unit as the main program. Other COBOL programs in that run unit are subprograms. There is no special source statement that marks a program as main or subprogram; the role depends on how the program enters the run unit.

This matters when the code ends or returns control. A main program normally finishes the run unit with STOP RUN or by returning to the caller outside that run unit. A subprogram usually returns control to the calling program with GOBACK or EXIT PROGRAM, depending on the coding standard used by the site.

Simple payroll application design

Here is a small payroll-style layout that a support developer might see in a batch application.

Program Role Main input or output
PAYMAIN Controls the run, reads employee records, and calls other modules. Employee master file
PAYVALD Checks employee status, department, and pay code. Validation return code
PAYCALC Calculates gross pay, tax, deduction, and net pay. Calculated payroll fields
PAYRPT Writes accepted, rejected, and control-total report lines. SYSOUT report

How the main program controls the flow

The main program should make the application flow easy to read. It opens files, loops through records, calls smaller modules, handles return codes, writes output, and closes files.

IDENTIFICATION DIVISION.
PROGRAM-ID. PAYMAIN.

PROCEDURE DIVISION.
    PERFORM OPEN-FILES
    PERFORM UNTIL WS-END-OF-FILE = 'Y'
        PERFORM READ-EMPLOYEE
        IF WS-END-OF-FILE NOT = 'Y'
            CALL 'PAYVALD' USING EMP-REC WS-VALID-RC
            IF WS-VALID-RC = ZERO
                CALL 'PAYCALC' USING EMP-REC PAY-RESULT
                CALL 'PAYRPT'  USING PAY-RESULT
            ELSE
                PERFORM WRITE-REJECT-REPORT
            END-IF
        END-IF
    END-PERFORM
    PERFORM CLOSE-FILES
    GOBACK.

This is only a sketch, but the shape is common. The main program reads the records and makes the top-level decisions. The called programs handle smaller pieces of the rule.

What belongs in a subprogram?

A subprogram is useful when the same rule is called from more than one place or when the rule is large enough to make the main program hard to read. Examples include tax calculation, interest calculation, address formatting, date validation, and report line building.

Good subprogram candidates

  • A calculation used by more than one batch job.
  • A validation rule shared by online and batch paths.
  • A report formatting routine that keeps the main flow short.
  • A database access routine with a clear input and output area.

Weak subprogram candidates

  • A two-line paragraph that is used only once.
  • A routine that changes global state without clear comments or return codes.
  • A module that needs too many unrelated fields in the USING list.

Data passed between programs

COBOL programs usually pass data through the CALL ... USING phrase. The calling program and called program must agree on the layout of the fields. If one side changes a copybook and the other side is not recompiled, the application can produce wrong values without an obvious compile error.

CALL 'PAYCALC' USING EMPLOYEE-RECORD
                     PAYROLL-RESULT
                     RETURN-AREA.

Keep the interface boring. Use clear copybook names, put return codes in a known place, and avoid sending every field in the application when the module only needs three values.

Files, DB2, and reports

Most COBOL applications are built around records. A batch program may read a sequential input file, update a VSAM file, call Db2 through embedded SQL, and write a report to SYSOUT. The application design should show which program owns each file or table update.

For file-heavy programs, review COBOL file operation and COBOL file I/O mode. Those topics explain why INPUT, OUTPUT, I-O, and EXTEND modes should match the way the application uses the data set.

Batch application checklist

  • Name the main program and each called module in the design note.
  • List input files, output files, VSAM clusters, Db2 tables, and reports.
  • Document every CALL ... USING interface with copybook names.
  • Define return codes for validation, calculation, and file errors.
  • Make restart points clear when the job updates files or tables.
  • Check whether called programs retain WORKING-STORAGE between calls.

Common mistakes

Putting every rule in the main program

A 5,000-line main program is hard to test and harder to support at 2 AM. Move repeated calculations and shared validation into called modules when the interface is stable.

Creating too many tiny modules

The opposite problem is also real. If a program calls twenty tiny modules to process one record, the support path becomes noisy. Keep module boundaries tied to business rules, files, or reports.

Ignoring retained storage

A called program can keep values in WORKING-STORAGE across calls, depending on how it ends and how it is compiled. That can be useful for counters, but it can also create a defect when a field from the previous employee is reused by accident. See COBOL Working Storage vs Local Storage and COBOL ending and reentering for the related behavior.

How to explain a COBOL application in an interview

A clear interview answer is short and practical: a COBOL application is a group of programs and resources that complete one business process. The first program in the run unit is the main program. Other programs are subprograms called for validation, calculation, database access, or reporting. Data is commonly passed with CALL ... USING, and the application is usually scheduled through JCL.

You can then give one example: a payroll application reads employee input, validates the record, calculates net pay, writes an output file, and prints a control report. That answer is much stronger than saying only that an application is a collection of programs.

Related COBOL tutorials

FAQ

Is a COBOL application the same as a COBOL program?

No. A COBOL program is one compiled source member. A COBOL application usually contains several programs, files, reports, JCL steps, and sometimes Db2 or CICS resources.

What is the main program in COBOL?

The main program is the first COBOL program in a run unit. It is not marked by a special COBOL statement; the way the run starts decides the role.

Why do COBOL applications use subprograms?

Subprograms keep repeated validation, calculation, file access, or report logic in smaller modules. That makes the application easier to test and support when the interface is clear.

What should I check before changing a COBOL application?

Check the JCL, called programs, copybooks, files, Db2 tables, return codes, and restart rules. A small copybook or file-layout change can affect several programs in the same application.

References

Sunday, 11 August 2013

COBOL DYNAM Compiler Option: Static vs Dynamic CALL

A COBOL program can call another program by writing CALL "PAYCALC" or by putting the program name in a data item and using CALL WS-PROGRAM-NAME. The DYNAM compiler option mainly affects the first form: CALL with a literal program name.

COBOL DYNAM compiler option diagram showing CALL literal with NODYNAM link-edit and DYNAM runtime load paths
Choose by CALL behavior.

What is the COBOL DYNAM compiler option?

DYNAM tells Enterprise COBOL to load separately compiled, nonnested programs dynamically when they are called with CALL literal. IBM documents the default as NODYNAM. The abbreviation is DYN, and NODYN is the abbreviation for NODYNAM.

With NODYNAM, a literal call is normally resolved through the link-edit step. With DYNAM, the called program is loaded at run time, and a later CANCEL can delete it from the run unit.

DYNAM vs NODYNAM

Option CALL literal behavior Good fit
NODYNAM The called program name is resolved through the link step. High-volume calls, stable subprograms, and programs where call path length matters.
DYNAM The called program is loaded dynamically at run time. Shared subprograms that change independently, optional routines, and cases where CANCEL is used to free storage.

CALL literal example

This is the form affected by DYNAM. The subprogram name is written directly in the source code.

CBL DYNAM

PROCEDURE DIVISION.
    CALL "TAXCALC" USING WS-INVOICE
                         WS-TAX-AMOUNT
    END-CALL
    GOBACK.

Compiled with DYNAM, this literal call is treated as a dynamic load at run time. Compiled with NODYNAM, the call is normally resolved when the program is linked.

CALL identifier is already dynamic

IBM documents that CALL identifier always results in a runtime load of the target program and is not affected by the DYNAM option. This is easy to miss when reviewing old code.

01 WS-PROGRAM-NAME      PIC X(8) VALUE "TAXCALC".

PROCEDURE DIVISION.
    CALL WS-PROGRAM-NAME USING WS-INVOICE
                               WS-TAX-AMOUNT
    END-CALL.

If a program already uses a data-name in the CALL statement, changing NODYNAM to DYNAM does not make that specific call more dynamic. It was already resolved by name at run time.

ON EXCEPTION with DYNAM

ON EXCEPTION can matter when a called program is missing from the runtime search path. IBM notes that for CALL literal, the exception condition can occur only when DYNAM is in effect. With NODYNAM, a missing statically resolved subprogram is usually caught earlier in the build or link process.

CALL "TAXCALC" USING WS-INVOICE
                     WS-TAX-AMOUNT
    ON EXCEPTION
       MOVE 16 TO WS-RETURN-CODE
END-CALL.

Do not use ON EXCEPTION as a substitute for proper deployment checks. It is a runtime safety path, not a reason to leave load libraries unclear.

Why use DYNAM?

DYNAM can make maintenance easier for common subprograms. If several applications call the same utility routine, a site may update that routine without relinking every caller, subject to local load library, binder, and change-control rules.

It can also help storage control in long-running programs. If a called program is no longer needed, CANCEL can remove the dynamically loaded program from the run unit.

Why keep NODYNAM?

NODYNAM is often better for call-heavy code. IBM performance guidance notes that DYNAM adds a longer path because the call goes through a library routine. The exact cost depends on the program and how often the call runs.

If a job calls the same small validation routine once for every input record, test carefully before switching to DYNAM. A call inside a ten-million-record loop is very different from a setup call that runs once.

Restrictions and cases to check

IBM documents restrictions for DYNAM. Do not use it for COBOL programs processed by the CICS translator or the CICS compiler option. IBM also documents restrictions for programs with EXEC SQL statements in certain environments, including CICS and Db2 call attach facility cases.

DLL use is another area to check. IBM states that if COBOL programs call programs linked as dynamic link libraries, the caller should be compiled with NODYNAM and DLL, not DYNAM.

Compile option example

Many shops set this option in a compile procedure rather than in the source. A source-level example is still useful when reading compiler listings or test programs.

CBL NODYNAM

IDENTIFICATION DIVISION.
PROGRAM-ID. PAYMAIN.

Before changing the option, check the compiler listing. The listing is the clean evidence of whether DYNAM or NODYNAM was in effect for the program you are testing.

Load library checks

Dynamic calls depend on the runtime search path. In batch, review the STEPLIB, job library setup, and site runtime libraries. In online regions, review the region procedure and program management rules used by the support team.

A common production problem is simple: the caller was compiled with DYNAM, but the called module was not in the expected library at execution time. The source code looked correct, but the runtime environment could not find the program.

Testing checklist

  • List every CALL literal and CALL identifier in the program.
  • Check whether the called program is linked with the caller or loaded from a runtime library.
  • Confirm CICS, SQL, CAF, DLL, and site standards before changing the option.
  • Run a missing-subprogram test if the application depends on ON EXCEPTION.
  • Compare CPU time and elapsed time for call-heavy programs.
  • Check load library order in the job or region where the program runs.

Migration review points

When moving older COBOL programs to a newer compiler, do not copy the old DYNAM setting blindly. Review how each called module is packaged, whether the program uses CICS or SQL, whether DLL rules apply, and whether the call sits inside a hot record loop.

For a high-volume batch driver, test one compile option change at a time. Keep the old listing, new listing, binder output, job statistics, and load-library evidence together so the next support person can see why the option was changed.

Common mistakes

Expecting DYNAM to affect CALL identifier

CALL WS-PROGRAM-NAME is already dynamic. The DYNAM option is mainly about nonnested, separately compiled programs called through CALL literal.

Changing the option without checking CICS or SQL

A batch test may work, but that does not prove the option is valid for a CICS or SQL environment. Check the actual execution environment before compiling production code.

Ignoring call frequency

A dynamic call in setup code may be harmless. A dynamic call inside a record loop can be expensive. Count the calls before arguing about the option.

Related Mainframe Forum guides

For nearby topics, read COBOL CALL statement examples, COBOL static call, COBOL COPY vs CALL, COBOL RENT compiler option, COBOL THREAD compiler option, and COBOL performance tuning tips.

External references

IBM documents the DYNAM compiler option, DYNAM performance considerations, and the COBOL CALL statement.

FAQ

What is the default for the COBOL DYNAM option?

IBM documents the default as NODYNAM.

Does DYNAM affect CALL identifier?

No. IBM documents that CALL identifier always causes a runtime load of the target program and is not affected by DYNAM.

When should I use NODYNAM?

Use NODYNAM when literal calls should be resolved through the link step, when call overhead matters, or when CICS, SQL, DLL, or site rules require it.

Can CANCEL unload a dynamically called program?

Yes. With dynamic calls, CANCEL can delete the called program from the run unit when it is no longer needed.

COBOL CALL Performance: Static, Dynamic, and Nested Calls

A COBOL batch job can spend a surprising amount of time transferring control between programs. The cost is small for one call, but it matters when a transaction driver calls the same validation module millions of times. The right choice depends on whether the subprogram name is fixed, whether the module must be loaded separately, and how the application is maintained.

COBOL CALL performance diagram comparing nested static and dynamic calls
Pick the call style.

What does CALL do in COBOL?

The CALL statement transfers control from one COBOL program to another program in the same run unit. The calling program passes data with the USING phrase, and the called program receives that data in its PROCEDURE DIVISION USING list.

CALL "TAXCALC" USING WS-GROSS-PAY
                     WS-TAX-AMOUNT
END-CALL

That example uses a CALL literal because the program name is hard-coded. A CALL identifier uses a data item to hold the program name, which lets the job choose the target at run time.

Static, dynamic, and nested calls at a glance

Call style Typical coding Best fit Tradeoff
Nested call CALL "INNER-PGM" inside a containing program Small helper logic that belongs inside one program source Less flexible for separate reuse
Static call CALL "TAXCALC" with NODYNAM Fixed subprogram names and stable batch applications Relink needed when called modules change
Dynamic call CALL WS-PROG-NAME or CALL literal with DYNAM Selectable routines, shared utility modules, plugin-style processing Runtime load and library lookup must be managed

CALL literal and CALL identifier

A CALL literal is easier for a reviewer to trace because the target name appears in the source. With NODYNAM, a nonnested CALL literal is normally handled as a static call. With DYNAM, that same source can behave like a dynamic call.

CALL "RATEEDIT" USING WS-RATE-AREA

A CALL identifier is dynamic. The program name comes from a working-storage item, parameter, file, or table. This is useful when one driver program chooses between several routines, but it also makes production diagnosis harder because the target module is not obvious from the statement alone.

01  WS-CALL-NAME PIC X(08) VALUE "RATEEDIT".

CALL WS-CALL-NAME USING WS-RATE-AREA
   ON EXCEPTION
      DISPLAY "CALL FAILED: " WS-CALL-NAME
END-CALL

Nested program calls

A nested program is coded inside another COBOL program. IBM documents nested calls as a structured way to keep helper logic close to the containing program and to reduce accidental changes to unrelated data. Nested programs can be called with a literal or identifier, subject to the scope rules of contained programs.

IDENTIFICATION DIVISION.
PROGRAM-ID. PAYDRVR.

PROCEDURE DIVISION.
    CALL "EDIT-PAY" USING WS-PAY-DATA
    GOBACK.

IDENTIFICATION DIVISION.
PROGRAM-ID. EDIT-PAY.
PROCEDURE DIVISION USING LS-PAY-DATA.
    GOBACK.
END PROGRAM EDIT-PAY.
END PROGRAM PAYDRVR.

Use nested programs for local helper routines that are not meant to be called across many load modules. Avoid them when the routine is a shared service that many programs must update independently.

Static CALL performance

A static call is usually faster to enter because the called program is resolved through link-edit or binder processing rather than found and loaded at run time. It also gives build-time visibility: if the called object is missing, the build process is more likely to expose the problem before the batch job starts.

The cost is maintenance. Static calls can make the load module larger, and a changed subprogram may require relink work. In a shop with many shared routines, that can turn one utility change into a batch of packaging work.

Dynamic CALL performance

Dynamic calls give the application more freedom. A program can call a module by name at run time, and a changed called program can often be replaced without rebuilding every caller. That is why dynamic calls are common for utility routines and configurable processing.

The tradeoff is runtime control. The correct module must be available through the job's load library search path, such as STEPLIB or site-standard runtime libraries. If the module is missing or the name is wrong, the failure happens during execution instead of during link-edit.

DYNAM and NODYNAM

The DYNAM compiler option tells Enterprise COBOL to treat nonnested, separately compiled CALL literal statements as dynamic calls. NODYNAM is the usual static choice for a fixed CALL literal. A CALL identifier is dynamic regardless of that option.

CALL "PAYCALC"     *> literal: static with NODYNAM, dynamic with DYNAM
CALL WS-PROG-NAME  *> identifier: dynamic

Do not decide this option from one statement alone. Check the compile option list, binder control, runtime libraries, and whether the program contains features with site restrictions, such as CICS or embedded SQL rules at your installation.

Parameter passing affects support more than speed

Most production issues around CALL do not come from the transfer itself. They come from mismatched parameters. IBM documents three common passing methods: BY REFERENCE, BY CONTENT, and BY VALUE.

Method What the called program gets Support note
BY REFERENCE Access to the caller's storage Changes in the called program affect the caller's data item.
BY CONTENT A copy of the caller's content The called program cannot change the original caller item.
BY VALUE A value, often for non-COBOL linkage Useful for C/C++ style calls, but both sides must agree.

Production checklist for CALL-heavy programs

  • List the top repeated calls in the job before changing compiler options.
  • Use CALL literal when the target program name is fixed and easy tracing matters.
  • Use CALL identifier only when the target truly needs to vary at run time.
  • Check whether DYNAM or NODYNAM is used by the compile JCL.
  • Verify the called module is available in the expected load library.
  • Match every CALL USING item with the called program's linkage layout.
  • Add ON EXCEPTION handling when a missing dynamic target should produce a clean message.

Common mistakes

Changing DYNAM without checking all calls

A compiler-option change can alter how fixed-name calls are loaded. Review every frequent CALL literal, especially in batch drivers and shared utility modules.

Using CALL identifier for a fixed name

If the target never changes, a literal is usually clearer. An identifier hides the target and makes source searches less useful during a production incident.

Passing the wrong layout

The called program does not know your intent. If the caller sends a 50-byte area and the callee expects 80 bytes, the symptom may appear as bad data, a protection exception, or a later logic error.

Related Mainframe Forum guides

For surrounding topics, read COBOL DYNAM Compiler Option, COBOL Application Structure, COBOL CALL by Reference, Content, and Value, COBOL CALL Statement, Static Call in COBOL, and COBOL RENT Compiler Option.

External references

IBM documents these rules in the Enterprise COBOL CALL statement, transferring control to another program, calling nested COBOL programs, and passing data pages.

FAQ

Is a static CALL always faster than a dynamic CALL?

Static calls usually avoid runtime load and lookup work, so they are often faster for repeated fixed-name calls. Measure the full job before changing a production compile option.

Is CALL identifier static or dynamic?

CALL identifier is dynamic. The target program name is taken from the value of the identifier at run time.

When should I use a nested COBOL program?

Use a nested program when the helper logic belongs inside one containing program and does not need to be separately shared by many applications.

What should I check first when a dynamic CALL fails?

Check the program name value, load library search path, compile option, and whether the called module exists under the expected name.

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