SIGSEGV is signal number 11 on Unix-like operating systems, sent to a program when it tries to access memory it isn’t allowed to touch. The name stands for “signal: segmentation violation,” and most programmers encounter it as the dreaded “segmentation fault” or “segfault” that crashes their program. It’s one of the most common errors in languages like C and C++ that give you direct control over memory.
How Your Computer Triggers a SIGSEGV
Every running program works with virtual memory addresses rather than physical ones. A hardware component called the Memory Management Unit (MMU) sits between your program and actual RAM, translating virtual addresses to physical locations and enforcing access permissions on every memory operation.
When your program tries to read, write, or execute memory, the MMU checks whether that virtual address maps to a valid physical location and whether your program has the right permissions for the type of access requested. If the address doesn’t map to anything, or your program is trying to write to read-only memory, the MMU can’t complete the request. It triggers a page fault, which is a hardware exception that pauses your program and hands control to the operating system kernel.
The kernel’s page fault handler examines what went wrong. Some page faults are routine (the data just needs to be loaded from disk into RAM), but if the access is genuinely illegal, the kernel sends SIGSEGV to your process. Unless your program has set up a custom signal handler, this terminates it immediately, often producing a core dump file for later analysis.
Two Types of Invalid Access
When SIGSEGV fires, the operating system includes a signal code that narrows down the problem:
- SEGV_MAPERR means the address your program tried to access doesn’t map to any valid object in memory. This is what happens with null pointer dereferences or wild pointers pointing into unallocated space.
- SEGV_ACCERR means the address does map to a real memory region, but your program doesn’t have the right permissions. For example, trying to write to a page marked read-only, or trying to execute data that isn’t marked as executable.
Every memory page has permission bits controlling whether it can be read, written, or executed. A page can also be marked completely inaccessible. If your code violates any of these protections, the kernel generates SIGSEGV.
Common Programming Mistakes That Cause It
Segfaults almost always trace back to a handful of bugs:
Null pointer dereference. This is the single most common cause. Your program has a pointer that was never assigned a valid address (or was explicitly set to null), and then tries to read or write through it. Since address zero is never mapped to valid memory, the MMU immediately faults.
Buffer overflow. Writing past the end of an array can corrupt adjacent memory or land on an unmapped page. Even if the overrun doesn’t immediately crash, it often corrupts other data structures in ways that cause a segfault later, making these bugs tricky to track down.
Use after free. If you free a block of memory and then continue using a pointer to it, that memory may have been returned to the operating system or reallocated for something else. Accessing it is undefined behavior and frequently triggers SIGSEGV.
Stack overflow. Every program gets a fixed amount of stack space (typically a few megabytes). Deeply recursive functions or large local variables can exhaust it. When the stack grows past its allocated region, the next write hits an unmapped page and you get a segfault.
Writing to string literals. In C, a string like "hello" is stored in read-only memory. If you assign it to a non-const pointer and then try to modify a character, the write hits a read-only page and triggers SEGV_ACCERR.
SIGSEGV vs. SIGBUS
Both signals indicate memory access problems, but they come from different root causes. SIGSEGV means you accessed an address that’s either unmapped or has the wrong permissions. SIGBUS (signal 7 or 10, depending on the platform) typically means the address is valid but something is physically wrong with the access, such as a misaligned read on hardware that requires alignment, or accessing a memory-mapped file that has been truncated. On macOS, some errors that show up as SIGSEGV on Linux appear as SIGBUS instead, which can confuse developers working across platforms.
How to Debug a Segfault
A segfault with no additional information tells you almost nothing. The key is getting a stack trace that shows exactly which line of code caused the illegal access.
The fastest approach is running your program through Valgrind. Compile with debug symbols (the -g flag), then run valgrind ./yourprogram. When the segfault occurs, Valgrind prints a stack trace pinpointing the source file, line number, and function where the bad access happened. It also tells you whether the address was null, previously freed, or something else entirely. For a null pointer dereference, you might see output like “Address 0x0 is not stack’d, malloc’d or (recently) free’d” along with the exact line number.
For more control, use GDB (the GNU Debugger). You can either run your program directly inside GDB or load a core dump file after a crash. GDB lets you inspect variable values, walk up and down the call stack, and examine the exact pointer that caused the fault. If you enable core dumps on your system and your program crashes, running gdb ./yourprogram core drops you right at the point of failure.
AddressSanitizer, a compiler feature available in GCC and Clang, is another powerful option. Compiling with -fsanitize=address instruments your code to detect out-of-bounds accesses, use-after-free bugs, and other memory errors at runtime, often catching problems before they escalate into a segfault.
SIGSEGV in Higher-Level Languages
Languages like Python, Java, and JavaScript manage memory for you, so you rarely see raw segfaults in normal code. When you do encounter one in these languages, it usually means there’s a bug in the language runtime itself, in a native extension module (like a C library called from Python), or that you’ve hit an interpreter bug. In Java, what would be a null pointer segfault in C surfaces as a NullPointerException instead, because the runtime catches the problem before it becomes a hardware fault.
In Rust, the language’s ownership and borrowing system prevents most segfault-causing bugs at compile time. Segfaults in Rust almost exclusively occur inside unsafe blocks where the compiler’s safety guarantees are explicitly bypassed.

