z/OS message

CEE3204S: Protection exception (0C4) under Language Environment

CEE3204S means Language Environment caught a protection exception, the program check that z/OS reports as system completion code 0C4. The program tried to use storage it isn't allowed to use, usually through a bad address, pointer or subscript.

Other names for this code

Also written as CEE3204, CEE3204S 0C4, CEE3204S protection exception, CEE3204S S0C4, LE 0C4, CEE344.

What it means

Language Environment (LE) is the runtime under COBOL, PL/I and C programs on z/OS. It traps program checks, the hardware interrupts that end a program when an instruction can't run. When the program check is a protection exception, LE writes CEE3204S. The message text says the system detected a protection exception and gives the system completion code 0C4. A second line names the compile unit, the entry point and the offset where it happened.

A protection exception means the instruction pointed at storage the program had no right to touch. The address might belong to z/OS, to another key, or to nothing the program ever obtained. The instruction itself is usually fine. The address it used is wrong.

The S at the end of the message ID means severe. If no condition handler deals with it, LE ends the thread. What the job log shows next depends on the runtime options. The step usually ends with abend S0C4, or with U4038 under some settings. The symbolic feedback code for this condition is CEE344, which is what a condition handler or a feedback code check sees.

Common causes

  • A subscript or index ran past the end of a table, so the program read or wrote storage well beyond it.
  • A called program has more items in its PROCEDURE DIVISION USING list than the caller passed. The extra LINKAGE SECTION items have no real address behind them.
  • A pointer, or a LINKAGE SECTION item set from one, was never set or was set from storage that has already been freed.
  • The program referred to a file's record area (the FD record) while the file was closed, for example after CLOSE or before the first OPEN.
  • A 24-bit (AMODE 24) program was handed an address above the 16 MB line, or a 31-bit address was cut short somewhere along a CALL chain. IBM puts the wrong AMODE first in its list of things to check.
  • The program overwrote its own storage earlier, such as a MOVE of a long field into a short one in LINKAGE, and a later instruction used the damaged address.

How to find the problem

  1. Read the second line of CEE3204S. It names the compile unit, the entry point and the offset, such as +000013C6. That points at the failing instruction.
  2. Match the offset to a statement in the compile listing. Compile with the LIST or OFFSET option if you don't keep listings.
  3. Look at the CEEDUMP (allocate a //CEEDUMP DD SYSOUT=* if the step doesn't have one). The traceback shows the chain of calls that led to the failure, so you can see who called whom with what.
  4. Check the IEA995I symptom dump for the reason code. Reason 4 means a real protection exception. Reason 10 or 11 means the address had no storage at all, which points to a garbage or freed pointer.
  5. If a tool such as Fault Analyzer or Abend-AID is installed, open its report for the job. It usually names the statement and shows the data items it used.

How to fix it

  • If a subscript is involved, add a range check, or compile with SSRANGE in test so the runtime reports the bad subscript instead of an 0C4.
  • Make the CALL and the called program agree on the number, order and length of parameters. Recompile both after any change to a shared copybook.
  • Set every pointer before use, and don't keep addresses to storage after it is freed.
  • Only touch a file's record area while the file is open. Move data you need later into WORKING-STORAGE first.
  • Check AMODE and RMODE when a 24-bit program is involved. Moving it to AMODE 31 usually removes the problem.

What it looks like

CEE3204S The system detected a protection exception (System Completion Code=0C4).
         From compile unit CLMEDIT at entry point CLMEDIT at compile unit offset +000013C6
IEF450I CLMRUN04 STEP030 - ABEND=S0C4 U0000 REASON=00000004

IBM documentation

IBM documentation: CEE3204S. Use the documentation for your installed release.

Report a correction to WND Software.

Questions

Is CEE3204S the same as S0C4?

It is the same error reported by a different part of the system. The processor raises the protection exception, z/OS calls it 0C4, and Language Environment writes CEE3204S with the program and offset.

Why does the job end with U4038 instead of S0C4 sometimes?

That depends on Language Environment runtime options such as ABTERMENC and TERMTHDACT. The cause is the same in both cases, so look at the CEE3204S line for where it happened.

Can a CEE3204S be caused by bad data rather than bad code?

Yes. A record with an out-of-range count can drive a subscript off the end of a table. The code fails on that record even though it ran correctly for months.