C++ Segmentation Fault Fix
In this tutorial, you'll learn about C++ Segmentation Fault Fix. We cover key concepts, practical examples, and best practices.
The Problem
Your C++ program crashes with Segmentation fault (core dumped):
$ ./myprogram
Segmentation fault (core dumped)
A segfault occurs when the program tries to access memory it does not have permission to access. This is always a bug in the code -- dereferencing a null pointer, accessing freed memory, or writing past the end of an array.
Quick Fix
Step 1: Compile with debug symbols and address sanitizer
g++ -g -fsanitize=address -o myprogram myprogram.cpp
./myprogram
AddressSanitizer (ASan) gives a precise report:
==12345==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55d8b7c3c123 bp 0x7ffc4a2b3f00 sp 0x7ffc4a2b3ee0 T0)
#0 0x55d8b7c3c123 in main /home/user/myprogram.cpp:5
Step 2: Check for null pointer dereference
WRONG -- using a pointer without checking:
int* ptr = nullptr;
*ptr = 42; // segmentation fault
RIGHT -- always check before dereferencing:
int* ptr = getValue();
if (ptr != nullptr) {
*ptr = 42;
} else {
std::cerr << "Error: ptr is null\n";
}
Step 3: Check array bounds
WRONG -- writing past the end of an array:
int arr[10];
for (int i = 0; i <= 10; i++) { // i goes to 10, but valid indices are 0-9
arr[i] = i;
}
RIGHT -- use correct bounds:
int arr[10];
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
Or use std::array or std::vector with .at() for bounds checking:
std::vector<int> vec(10);
for (int i = 0; i < vec.size(); i++) {
vec.at(i) = i; // throws std::out_of_range if i >= vec.size()
}
Step 4: Check for dangling pointers
WRONG -- using memory after it is freed:
int* ptr = new int(42);
delete ptr;
*ptr = 100; // undefined behavior, likely segfault
RIGHT -- set pointer to nullptr after delete:
int* ptr = new int(42);
delete ptr;
ptr = nullptr;
// Or use smart pointers
std::unique_ptr<int> ptr = std::make_unique<int>(42);
// ptr is automatically freed when it goes out of scope
Step 5: Check for stack overflow
Deep recursion without a base case causes stack overflow:
WRONG -- infinite recursion:
int factorial(int n) {
return n * factorial(n - 1); // no base case, infinite recursion
}
RIGHT -- add a base case:
int factorial(int n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1);
}
Or convert to iteration for very deep calls.
Step 6: Use Valgrind for detailed analysis
g++ -g -o myprogram myprogram.cpp
valgrind --leak-check=full ./myprogram
Valgrind reports invalid memory accesses, use-after-free, and memory leaks:
==12345== Invalid write of size 4
==12345== at 0x109123: main (myprogram.cpp:5)
==12345== Address 0x0 is not stack'd, not malloc'd or (recently) free'd
Use DodaTech's Debug Inspector to analyze core dumps and locate the exact line of the segfault without rebuilding.
Prevention
- Initialize all pointers to
nullptror a valid address. - Use
std::unique_ptrandstd::shared_ptrinstead of raw pointers. - Use
std::vector::at()instead ofoperator[]for bounds checking. - Compile with
-Wall -Wextra -fsanitize=addressduring development. - Run Valgrind or ASan in CI/CD to catch memory errors before release.
- Enable core dumps with
ulimit -c unlimitedfor post-mortem analysis.
Common Mistakes with segfault
- Forgetting
deriving (Show, Eq)on custom data types needed for debugging - Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists
These mistakes appear frequently in real-world CPP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro