When a C or C++ application finishes running, it sends back a numeric value to the operating system. This value is called an exit code. Exit codes tell us whether the program ran without problems or hit some kind of error along the way.

How the exit() Function Works in C and C++

The exit() function stops a program right where it is. It accepts a single integer argument, which becomes the program’s return value.

void exit(int return_code)

A return value of 0 (or EXIT_SUCCESS) means the program completed as expected. Any non-zero return value (or EXIT_FAILURE) signals that something went wrong. Among all possible exit codes, values 1, 2, 126 through 165, and 255 carry predefined meanings. Avoid picking these numbers for your own custom codes.

Note: Any value above 255 wraps around using modulo 256. Calling exit(9999) actually produces an exit code of 15, because 9999 % 256 = 15.

Common Exit Codes in C/C++ and Their Meanings

The table below lists widely recognized exit codes and what each one signals.

Exit Code Signal Meaning
1 — Minor runtime failure
2 — Serious runtime failure (rarely seen)
127 — Requested command was not located
132 SIGILL Illegal CPU instruction or damaged binary
133 SIGTRAP Integer divided by zero
134 SIGABRT Failed assertion or forced abort
136 SIGFPE Floating-point error or integer overflow
137 — Program consumed too much memory
138 SIGBUS Misaligned memory access
139 — Segmentation fault — tried to access unallocated memory
158/152 SIGXCPU CPU time quota exceeded
159/153 SIGXFSZ Output file size quota exceeded

These exit codes make troubleshooting much easier. If your program returns 139, for instance, you know it attempted to reach a memory address it had no permission to touch. Start fixing pointer-related bugs from there.

Practical Scenarios That Produce Specific Exit Codes

Accessing an Array Beyond Its Bounds (Exit Code 139)

Declaring an array with 100 slots but trying to read position 100001 triggers a segmentation fault. The operating system halts the program because it tried to reach restricted memory space.

int arr[100] = {0};
cout << arr[100001];  // causes segmentation fault

Dividing an Integer by Zero (Exit Code 136)

Attempting to compute a / b when b holds the value zero raises a floating-point signal. The system terminates the process and returns exit code 136.

int a = 1, b = 0;
cout << a / b;  // triggers SIGFPE

Endless Loop Consuming All Resources (Exit Code 137)

An infinite loop that keeps allocating local arrays on every iteration exhausts available memory fast. The system kills the process once resource limits are breached.

for (;;) {
    int arr[10000];
}
Warning: Exit code 137 can also appear when an external process (like an OOM killer on Linux) forcefully terminates your program. Check system logs with dmesg to confirm.

Why Exit Codes in C and C++ Matter for Debugging

Exit codes give programmers a quick way to identify the category of failure without reading through log files. When an application crashes during automated testing or production deployment, the returned exit code often points straight to the root cause.

A code of 139 means pointer misuse. A code of 136 means arithmetic gone wrong. A code of 137 means your program ate more memory than allowed.

Tip: Check the exit code of the last command in a terminal by running echo $? immediately after execution.

Getting familiar with standard exit codes saves real debugging time, especially when working on large codebases or multi-process systems where one crashed component can affect everything else.

FAQs

Exit code 0 means the program finished without errors. It is equivalent to returning EXIT_SUCCESS from the main() function.

Exit code 139 indicates a segmentation fault. Your program tried to read or write memory it was not allocated. Check for out-of-bounds array access or dangling pointers.

Values above 255 wrap around using modulo 256. For example, exit(9999) produces exit code 15 because 9999 % 256 = 15.

Both terminate the program with a status code. The difference: return from main() destroys local automatic objects, while exit() does not. Both destroy static objects.

Avoid codes 1, 2, 126–165, and 255. These have predefined system meanings. Use codes in the 64–113 range for custom error conditions instead.

Willie has over 15 years of experience in Linux system administration and DevOps. After managing infrastructure for startups and enterprises alike, he founded Command Linux to share the practical knowledge he wished he had when starting out. He oversees content strategy and contributes guides on server management, automation, and security.