A segmentation fault (Signal 11) occurs when a program attempts to access memory that it doesn't have permission to access. This is one of the most common crashes in C/C++ development, often indicating serious memory management issues.
The classic case where your code tries to access memory through a null pointer:
int *ptr = NULL;
*ptr = 42; // Boom! SIGSEGV
Modern systems typically catch this at address 0, but any invalid memory address will trigger the same error.
Excessive recursion or large stack allocations can exhaust the stack space:
void recursive_function() {
char large_array[1024*1024]; // 1MB stack allocation
recursive_function();
}
This manifests differently from heap overflow and requires different debugging approaches.
Memory management errors like double free or accessing freed memory:
char *str = malloc(10);
free(str);
strcpy(str, "oops"); // Use after free
Tools like Valgrind or AddressSanitizer are invaluable for detecting these issues.
Writing past the end of allocated memory:
char buffer[10];
for (int i = 0; i <= 10; i++) {
buffer[i] = 'a'; // Off-by-one error
}
This can corrupt adjacent memory and lead to later segmentation faults.
Race conditions in multithreaded programs can cause invalid memory access:
// Shared global variable
int *shared_ptr = NULL;
void thread_func() {
if (shared_ptr) {
*shared_ptr = 100; // Potential SIGSEGV if another thread freed this
}
}
When facing a SIGSEGV:
- Use
gdb
to get a backtrace (bt
command) - Enable core dumps (
ulimit -c unlimited
) - Compile with debug symbols (
-g
) - Use sanitizers (
-fsanitize=address
) - Check system logs (
dmesg
on Linux)
- Always initialize pointers
- Use smart pointers in C++
- Implement bounds checking
- Adopt RAII patterns
- Regularly run static analysis tools
That dreaded SIGSEGV
or segmentation fault occurs when your program attempts to access memory it doesn't have permission to use. Let's break down the most common culprits:
The classic case - trying to access memory through a pointer that's either uninitialized or already freed:
int *ptr = NULL;
*ptr = 42; // Boom! SIGSEGV
char *str = (char *)malloc(10);
free(str);
strcpy(str, "oops"); // Use after free
Recursion without proper termination or large stack allocations can blow your stack:
void infinite_recursion() {
infinite_recursion(); // Eventually crashes
}
int main() {
int huge_array[10000000]; // Stack size exceeded
}
Writing past allocated memory boundaries:
char buffer[10];
strcpy(buffer, "This string is way too long!"); // Corrupts adjacent memory
1. Use AddressSanitizer (-fsanitize=address):
The best tool for catching memory errors during development.
2. Core Dumps Analysis:
ulimit -c unlimited
then examine with gdb:
gdb ./your_program core
3. Backtrace the Crash:
bt full
in gdb shows the exact call stack.
- Always initialize pointers to NULL
- Use smart pointers (C++) or RAII patterns
- Validate array indices before access
- Enable compiler warnings (-Wall -Wextra)
Sometimes the fault occurs in system libraries due to:
// Mismatched header/binary versions
#include
// Linked against new_version.so
Verify with ldd
and check symbol versions.
Race conditions can lead to segfaults that only appear sometimes:
void *thread_func(void *arg) {
static int *ptr = NULL;
if (!ptr) ptr = malloc(sizeof(int));
// Race condition: another thread might free ptr
*ptr = 42;
return NULL;
}