Runtime (SIGFPE / Signal)Runtime Signals5 min read

Floating Point Exception in C (SIGFPE): Root Causes & Fixes

A floating point exception (SIGFPE) can report an arithmetic fault, including integer division or remainder by zero and an unrepresentable signed quotient such as INT_MIN / -1. These integer operations have undefined behavior in C: a signal is possible, not guaranteed. On Linux x86/x86-64, SIGFPE is signal 8; shells such as Bash commonly report status 136 (128 + 8). Other platforms and execution tools may report failures differently.

Quick Fix Summary

Always validate divisors before performing division or modulo operations (if (divisor == 0) { ... }). For signed integers, also guard against INT_MIN / -1.

An arithmetic exception illustrated by division by zero and a warning symbol.
An arithmetic exception illustrated by division by zero and a warning symbol.

Signal & Exit Code Reference

The numbers below are Linux x86/x86-64 examples using the Bash convention 128 + signal number, not portable C exit codes. SIGSEGV is included for comparison; this article concerns SIGFPE. Undefined behavior does not guarantee a signal or a core dump.

Signal NameSignal #Shell Exit Code (128 + N)Trigger Condition & Meaning
SIGFPE8136Arithmetic-fault signal. On Linux x86/x86-64, a hardware integer divide error commonly produces SIGFPE; enabled floating-point traps can also produce it.
SIGSEGV11139Memory-access signal, shown for comparison. Invalid memory accesses may cause SIGSEGV, but undefined behavior in C does not guarantee it.

Why This Error Happens

Integer Division Can Raise SIGFPE

On Linux x86/x86-64, an executed hardware integer divide instruction with a zero divisor or an unrepresentable quotient raises a divide-error exception. The kernel normally delivers SIGFPE. In C, these operations have undefined behavior: optimization, architecture, signal handlers, and execution environments can change the result. Do not use a crash or its absence to decide whether code is safe.

Floating-Point Results Depend on the Environment

On typical IEEE 754 implementations with floating-point traps disabled, a nonzero finite value divided by 0.0 produces an infinity, while 0.0 / 0.0 produces NaN. Enabled traps can instead raise SIGFPE. The GNU feenableexcept function is a nonstandard extension, not a portable C requirement. Check the implementation and floating-point environment rather than assuming every division by zero behaves alike.

Guard an Unrepresentable Signed Quotient

On two's-complement implementations, INT_MIN / -1 cannot be represented as an int; INT_MIN % -1 is also undefined when the quotient is unrepresentable. On a typical 32-bit int, INT_MIN is -2147483648 and INT_MAX is 2147483647. Guard this pair before division or remainder, as well as guarding a zero divisor. Promoting to another type is only safe when that type can actually represent the result.

Top Root Causes & Specific Code Fixes

1. Integer Division or Modulo by Zero

Computing a / b or a % b when b evaluates to 0 (e.g. uninitialized input, empty array count, or loop counter reaching zero).

Broken Pattern
int count = 0;
int total = 100;
int average = total / count; // Undefined behavior; may raise SIGFPE
Corrected Pattern
int count = 0;
int total = 100;
int average = (count != 0) ? (total / count) : 0; // Safe check
Illustrative diagnostic (not executed):Floating point exception (core dumped)

2. Signed Integer Overflow: INT_MIN / -1

On two's-complement implementations, INT_MIN / -1 has an unrepresentable signed quotient. This is undefined behavior in C and may raise SIGFPE on Linux x86/x86-64.

Broken Pattern
#include <limits.h>
int a = INT_MIN;
int b = -1;
int c = a / b; // Undefined behavior; may raise SIGFPE
Corrected Pattern
#include <limits.h>
int a = INT_MIN;
int b = -1;
if (b == 0 || (a == INT_MIN && b == -1)) {
    return -1; // Reject invalid or unrepresentable division
}
int c = a / b;
Illustrative diagnostic (not executed):Floating point exception (core dumped)

3. Unchecked Dynamic Modulo Operations

A zero divisor in val % size is undefined behavior. A negative size is not itself an arithmetic fault, but rejecting nonpositive capacities prevents invalid bucket or array indexing.

Broken Pattern
int capacity = 0;
int bucket = key % capacity; // Undefined behavior; may raise SIGFPE
Corrected Pattern
int capacity = 0;
if (capacity <= 0) {
    return -1;
}
int bucket = key % capacity;
Illustrative diagnostic (not executed):Floating point exception (core dumped)

Complete Broken and Corrected Programs

Compare the source before running it. The broken program is intentionally incorrect; its behavior can depend on the compiler and platform.

Read the broken program
#include <stdio.h>

int main(void) {
    printf("=== Demonstrating Floating Point Exception ===\n");
    int numerator = 100;
    int denominator = 0; // Invalid divisor

    printf("Attempting integer division: %d / %d...\n", numerator, denominator);
    // Undefined behavior: may raise SIGFPE on Linux x86/x86-64
    int result = numerator / denominator;

    printf("Result: %d\n", result);
    return 0;
}
Open broken program in compiler
Read the corrected program
#include <stdio.h>
#include <limits.h>

int safe_divide(int a, int b, int *out_result) {
    if (b == 0) {
        return -1; // Error: division by zero
    }
    // Protect against INT_MIN / -1 signed overflow
    if (a == INT_MIN && b == -1) {
        return -2; // Error: signed integer overflow
    }
    *out_result = a / b;
    return 0; // Success
}

int main(void) {
    printf("=== Safe Integer Division Demo ===\n");

    int test_cases[][2] = {
        {100, 5},
        {100, 0},
        {INT_MIN, -1},
        {42, 7}
    };

    int num_tests = sizeof(test_cases) / sizeof(test_cases[0]);
    for (int i = 0; i < num_tests; i++) {
        int a = test_cases[i][0];
        int b = test_cases[i][1];
        int result = 0;

        int status = safe_divide(a, b, &result);
        if (status == 0) {
            printf("[OK] %d / %d = %d\n", a, b, result);
        } else if (status == -1) {
            printf("[GUARDED] Division by zero rejected for %d / %d\n", a, b);
        } else if (status == -2) {
            printf("[GUARDED] INT_MIN / -1 overflow rejected for %d / %d\n", a, b);
        }
    }

    printf("All divisions validated safely without SIGFPE crashes.\n");
    return 0;
}
Open corrected program in compiler

Expected output from the corrected program

Reference output, not a live execution result. This example assumes a 32-bit int; the displayed INT_MIN value can differ on other implementations.

=== Safe Integer Division Demo ===
[OK] 100 / 5 = 20
[GUARDED] Division by zero rejected for 100 / 0
[GUARDED] INT_MIN / -1 overflow rejected for -2147483648 / -1
[OK] 42 / 7 = 6
All divisions validated safely without SIGFPE crashes.

Debugging Techniques and Commands

GDB Backtrace (Identify Crash Line)
gcc -g main.c -o app && gdb -batch -ex "run" -ex "bt" ./app

Runs the program in GDB and prints the exact source file and line number that triggered the SIGFPE arithmetic trap.

Compiler Division-by-Zero Warnings
gcc -Wall -Wextra -Wdiv-by-zero main.c

GCC detects literal division by zero at compile time and emits warnings before code is ever executed.

UndefinedBehaviorSanitizer (UBSan)
gcc -fsanitize=undefined -g main.c -o app && ./app

Instruments compiled binary to log detailed runtime diagnostics for integer division by zero and signed integer overflows.

Frequently Asked Questions

Why is it called a floating-point exception when I only divided integers?

SIGFPE covers arithmetic exceptions, not only floating-point operations. For example, Linux on x86/x86-64 can deliver it for a hardware integer divide error. Signal numbers and exact behavior depend on the platform.

Does floating-point division (float/double) raise SIGFPE in C?

It depends on the implementation and floating-point environment. Typical IEEE 754 implementations produce infinity or NaN with traps disabled; enabled traps may raise SIGFPE. GNU feenableexcept is nonstandard.

Can I catch SIGFPE with signal() or sigaction() in C?

A handler can be installed, but returning normally after a computational exception is not a portable recovery technique and may repeatedly fault or have undefined behavior. Prevent invalid arithmetic before executing it; do not rely on a handler or siglongjmp to make undefined C arithmetic safe.

Related errors