A segmentation fault means a program tried to access memory it wasn’t allowed to, and the operating system stepped in to prevent a crash.
Common Causes and Fixes
-
Dangling Pointers/Use-After-Free: A program is trying to use a pointer to memory that has already been freed. This is a classic C/C++ bug.
- Diagnosis: Run the program with
valgrind --leak-check=full --show-leak-kinds=all. Valgrind is a dynamic analysis tool that detects memory errors. Look for "Invalid read" or "Invalid free" errors, which often point to use-after-free issues. - Fix: Review the code around the reported memory access. Ensure that any pointer is valid and points to allocated memory before dereferencing it. If a pointer is freed, set it to
NULLimmediately afterward to prevent accidental reuse. - Why it works: Valgrind tracks memory allocations and deallocations. By flagging accesses to freed memory, it highlights precisely where the program violates memory safety rules. Setting pointers to
NULLafter freeing makes subsequent attempts to use them result in a predictableNULLpointer dereference, which is easier to debug than a wild memory access.
- Diagnosis: Run the program with
-
Buffer Overflow/Underflow: Writing data beyond the bounds of an allocated buffer. This can corrupt adjacent memory or overwrite control structures, leading to a crash when that corrupted data is later used.
- Diagnosis: Again,
valgrindis your best friend. Look for "Invalid write" errors originating from a write operation that exceeds the buffer’s allocated size. - Fix: Implement bounds checking for all buffer operations. Use safer functions like
strncpyinstead ofstrcpy, andsnprintfinstead ofsprintf. Ensure the destination buffer is large enough for the data being copied, or truncate the data if necessary. - Why it works:
valgrinddetects writes that go outside the allocated memory regions. By using safer, size-aware functions and ensuring sufficient buffer space, you prevent the program from corrupting memory it doesn’t own.
- Diagnosis: Again,
-
Stack Overflow: The program has exhausted the available stack space, typically due to excessively deep recursion or very large local variables.
- Diagnosis: Check
ulimit -s. This shows the current stack size limit in kilobytes. If the program is crashing deep in a recursive function, it’s a strong indicator. You can also usegdband examine the call stack (btcommand) for an unusually large number of frames. - Fix: Increase the stack size limit using
ulimit -s unlimited(for the current session) or by modifying/etc/security/limits.conf. For recursive functions, refactor them to use iteration or tail-call optimization if possible. For large local variables, consider allocating them on the heap instead. - Why it works: Increasing the stack limit provides more memory for function call frames. Refactoring recursion or moving large data to the heap reduces the demand on the stack.
- Diagnosis: Check
-
Null Pointer Dereference: Attempting to access memory through a pointer that is
NULL. This is a specific case of invalid memory access.- Diagnosis:
gdb <your_program>. When the segmentation fault occurs,gdbwill stop. Use thebtcommand to see the call stack. The frame where the fault occurred will often show aNULLpointer being dereferenced. The error message ingdbmight be "Cannot access memory at address 0x0". - Fix: Add checks before dereferencing pointers to ensure they are not
NULL. For example,if (ptr != NULL) { *ptr = value; }. - Why it works: The
NULLpointer has a defined address (usually 0), but it’s not valid for general memory access. Explicitly checking forNULLprevents the program from attempting this illegal operation.
- Diagnosis:
-
Corrupted Pointers/Data Structures: Memory corruption from other errors (like buffer overflows) can damage pointers or critical data structures, leading to a segfault later when these corrupted items are used.
- Diagnosis: This is harder and often requires a combination of
valgrind(to catch the initial corruption) andgdb(to trace the consequence). Ifvalgrindshows memory corruption far from where the segfault occurs, it’s a clue. - Fix: Fix the root cause of the memory corruption, which is often a buffer overflow or use-after-free elsewhere in the program. Thoroughly review code that writes to memory, especially around array boundaries and data structure manipulation.
- Why it works: By identifying and fixing the initial memory corruption event, you prevent the subsequent, seemingly unrelated, segfault that occurs when the corrupted data is finally processed.
- Diagnosis: This is harder and often requires a combination of
-
Incorrect Use of Libraries/System Calls: Passing invalid arguments to library functions or system calls, or misinterpreting their return values, can lead to memory corruption or segmentation faults.
- Diagnosis: Consult the documentation for the library function or system call that is being called in the stack trace. Pay close attention to argument types, valid ranges, and expected return values (especially error codes like
-1orNULL). - Fix: Correct the arguments being passed according to the library’s or system’s specifications. Ensure error conditions are properly handled. For example, if a
malloccall returnsNULL, the program should not attempt to use the returned pointer. - Why it works: Libraries and system calls often perform internal memory operations. Providing them with incorrect inputs can cause them to misbehave, leading to memory access violations. Adhering to their contracts ensures they operate safely.
- Diagnosis: Consult the documentation for the library function or system call that is being called in the stack trace. Pay close attention to argument types, valid ranges, and expected return values (especially error codes like
After fixing these, you might hit a "Bus error" if the memory access was not only invalid but also misaligned with the processor’s requirements.