Why Null Pointer Dereferences Cause Segfaults in C

Dereferencing a null pointer in C typically results in a runtime segmentation fault because the operating system and CPU hardware work together to prevent unauthorized memory access. In modern systems, a null pointer generally resolves to virtual memory address zero, which the operating system deliberately leaves unmapped or marks as restricted. When a program attempts to read or write to this address, the hardware triggers a memory protection fault, prompting the operating system to abort the process via a segmentation violation signal (SIGSEGV).

The Concept of a Null Pointer

In the C programming language, a pointer holds the memory address of an object or function. A null pointer is a reserved value indicating that the pointer does not refer to any valid memory location. In standard implementations on modern architectures, NULL is represented as an integer constant zero cast to a void * pointer ((void *)0).

Dereferencing occurs when a program uses the unary * operator or arrow -> operator to access or modify the data residing at the address stored in the pointer:

int *ptr = NULL;
int value = *ptr; // Dereferencing NULL

The C standard categorizes dereferencing a null pointer as Undefined Behavior. This means the language specification does not dictate what must happen. However, on virtually all modern consumer and server operating systems, this operation reliably triggers a segmentation fault.

Virtual Memory and the Memory Management Unit

To understand why the crash occurs, it is necessary to examine how memory is structured in modern computing. Processes do not interact directly with physical RAM. Instead, they operate within an isolated virtual address space managed cooperatively by the operating system kernel and a hardware component called the Memory Management Unit (MMU).

Virtual memory is segmented into fixed-size blocks called pages (commonly 4 KB in size). The operating system maintains page tables that map these virtual pages to physical memory frames, along with access permissions such as read, write, or execute.

Why Address Zero is Protected

During process initialization, the operating system intentionally leaves the lowest page of the virtual address space (including address 0x00000000) unmapped or explicitly configured with no access permissions (neither readable nor writable).

Operating system designers do this by design precisely to catch null pointer dereferences and similar bugs. Because programmers frequently initialize pointers to zero, reserving the first page guarantees that any accidental attempt to read from or write to a null pointer will immediately fail rather than silently corrupting memory or returning garbage data.

The Sequence Leading to a Segmentation Fault

When the program executes an instruction that dereferences a null pointer, the following low-level sequence takes place:

  1. Instruction Execution: The CPU encounters an instruction requesting a load or store operation targeting virtual address 0.
  2. Address Translation: The CPU passes the virtual address to the MMU to translate it into a physical RAM address using the process's page table.
  3. Hardware Trap (Page Fault): The MMU examines the entry for address 0 and detects that the page is either non-existent in physical memory or designated as inaccessible. The MMU immediately halts execution of the instruction and raises a hardware exception known as a page fault.
  4. Kernel Mode Transition: The CPU switches execution context from user mode to kernel mode and jumps to the operating system's page fault handler.
  5. Violation Detection: The kernel examines the cause of the page fault and the requested address. Since the address falls within the reserved zero-page region, the kernel determines that the process attempted an illegal memory access rather than a legitimate memory-loading event (like dynamic paging).
  6. Signal Dispatch (SIGSEGV): The kernel dispatches a SIGSEGV (Segmentation Violation) signal to the offending process.
  7. Process Termination: By default, processes do not handle SIGSEGV. The operating system terminates the process immediately, prints an error message such as Segmentation fault (core dumped), and prevents the program from compromising the integrity of the system or its own state.