System abend

S0C4: Protection exception

An S0C4 abend means the program tried to use storage it isn't allowed to touch, or an address where no storage exists. Reason code 4 is a protection exception, and reason codes 10 and 11 mean the address doesn't point to storage the program has obtained.

Also written as 0C4, SOC4, abend 0C4, system abend 0C4, S0C4-4, S0C4-11, protection exception.

What it means

Every piece of storage in z/OS carries a storage key, and an ordinary program can only change storage whose key matches its own. When a program stores into storage it isn't allowed to change, the processor raises a protection exception. When a program refers to an address with no storage behind it, the processor raises a translation exception. z/OS reports both as system completion code 0C4, and the reason code tells them apart.

  • Reason 4 is a protection exception. The address is real, but the program may not change it (or, for fetch-protected storage, read it). Writing through a null pointer ends up here, because the lowest addresses in storage are protected.
  • Reason 10 is a segment-translation exception. No storage has been obtained anywhere near the address. A garbage pointer or a truncated address is the usual source.
  • Reason 11 is a page-translation exception. The page the address falls in was never obtained or has been freed. A pointer to storage that another routine already released often causes it.

Common causes

  • A table subscript or index went past the end of an OCCURS table, so the program read or wrote storage beyond it.
  • A called program's LINKAGE SECTION doesn't match the caller's USING list. If the caller passes three parameters and the subprogram expects four, the fourth address is whatever happened to be in storage.
  • The program used a LINKAGE SECTION item or a pointer before setting it (a missing SET ADDRESS OF), or kept using a pointer after the storage it pointed to was freed.
  • The program referred to a file's record area when the file wasn't open, either before the OPEN or after the CLOSE.
  • An AMODE 24 program received an address above the 16 MB line. It only uses the low 24 bits of the address, so it reaches the wrong storage.

How to find the problem

  1. Find CEE3204S (Language Environment) or the IEA995I symptom dump in the job log. Note the reason code (INTC in IEA995I), the load module name and the offset.
  2. Work out the failing instruction. For reason 4, the PSW points just past it, so subtract the ILC from the offset. For reason 10 or 11, the PSW points at the failing instruction itself. Match the offset to the compiler listing (LIST or OFFSET option) to find the statement.
  3. Decode the instruction to see which registers formed the address, and read them from the dump or a tool such as Fault Analyzer or Abend-AID. Then trace where that value came from.
  4. If the statement uses LINKAGE SECTION fields, compare the CALL in the caller with the PROCEDURE DIVISION USING in the subprogram, field by field.

How to fix it

  • Add range checks for subscripts, or compile with SSRANGE in test so overruns are caught when they happen.
  • Make the caller's and the subprogram's parameter lists match, and recompile both after any change to a shared copybook.
  • Set every pointer and LINKAGE SECTION address before using it, and stop using an address once its storage has been freed.
  • Open files before touching their record areas, and copy any data you need after the CLOSE to WORKING-STORAGE.
  • Link AMODE 24 routines as AMODE 31 if they can run that way, or pass them storage below the line.

What it looks like

IEA995I SYMPTOM DUMP OUTPUT
  SYSTEM COMPLETION CODE=0C4  REASON CODE=00000011
   PSW AT TIME OF ERROR  078D1000   8002B3C6  ILC 4  INTC 11
     ACTIVE LOAD MODULE           ADDRESS=0002A000  OFFSET=000013C6
     NAME=CLMEDIT
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=00000011

Questions

What is the difference between S0C4 reason 4 and reason 11?

Reason 4 means the storage exists but the program may not use it that way. Reason 11 means nothing is there, usually because the pointer is wrong or the storage was freed.

Why does an S0C4 come and go between runs?

Because the program is using an address it shouldn't. Whether that address happens to be valid depends on what else is in storage at the time, so the same bug can abend one day and quietly overwrite data the next.

How does S0C4 show up in CICS?

As the transaction abend ASRA. The CICS transaction dump shows the program check and its interrupt code, such as 4 or 11.