C++ Segmentation Fault: Causes, Debugging, and Prevention
이 글의 핵심
Quick reference for segmentation faults: ten common causes, GDB/Valgrind/ASan usage, and habits that prevent invalid memory access in C++.
Longer walkthrough: segmentation fault (GDB & ASan).
Introduction: “Segmentation fault (core dumped)”
“My program crashes out of nowhere”
In C++, a segmentation fault is a crash from invalid memory access. Typical causes include null pointers, dangling pointers, and buffer overruns.
// Null dereference
int* ptr = nullptr;
*ptr = 42; // Segmentation fault
// Use-after-free
int* ptr = new int(42);
delete ptr;
*ptr = 99; // Undefined behavior / likely crash
// Buffer overrun
int arr[5];
arr[1000000] = 42; // May segfault
This article covers:
- Ten common causes of segmentation faults
- Debugging workflows
- Prevention patterns
- Practical fixes
Table of contents
1. What is a segmentation fault?
Definition
A segmentation fault occurs when a process accesses memory it is not allowed to use.
// Conceptual layout: [text] [data] [heap] ... [stack]
// invalid region ↑
int* ptr = (int*)0x12345678; // arbitrary address
*ptr = 42; // likely segfault
Names by platform
- Linux/Unix: Segmentation fault (SIGSEGV)
- Windows: Access Violation (0xC0000005)
- macOS: EXC_BAD_ACCESS
2. Ten common causes
1. Null pointer dereference
int* ptr = nullptr;
*ptr = 42;
// Prefer
if (ptr != nullptr) {
*ptr = 42;
}
2. Dangling pointer
int* ptr = new int(42);
delete ptr;
*ptr = 99;
// After delete
ptr = nullptr;
3. Array out of bounds
int arr[5];
arr[100] = 42;
if (index >= 0 && index < 5) {
arr[index] = 42;
}
4. Stack overflow (infinite recursion)
void foo() {
foo();
}
void foo(int n) {
if (n <= 0) return;
foo(n - 1);
}
5. Huge local array on the stack
void foo() {
int arr[10000000]; // may overflow default stack
}
void foo() {
auto arr = std::make_unique<int[]>(10000000);
}
6. Returning address of a local variable
int* foo() {
int x = 42;
return &x;
}
std::unique_ptr<int> foo() {
return std::make_unique<int>(42);
}
7. Uninitialized pointer
int* ptr;
*ptr = 42;
int* ptr = nullptr;
// or allocate valid storage
8. Bad cast / wrong type
int x = 42;
std::string* ptr = (std::string*)&x;
ptr->length(); // UB / likely crash
int* ptr = &x;
9. Double delete
int* ptr = new int(42);
delete ptr;
delete ptr;
delete ptr;
ptr = nullptr;
10. Modifying a string literal
char* str = "Hello";
str[0] = 'h'; // read-only on typical implementations
char str[] = "Hello";
str[0] = 'h';
3. Debugging
GDB
g++ -g -o myapp main.cpp
gdb ./myapp
(gdb) run
(gdb) backtrace
(gdb) frame 0
(gdb) print ptr
Valgrind
valgrind --leak-check=full ./myapp
AddressSanitizer
g++ -fsanitize=address -g -o myapp main.cpp
./myapp
4. Prevention
Smart pointers
auto ptr = std::make_unique<int>(42);
auto ptr = std::make_shared<int>(42);
Containers and bounds-checked access
std::vector<int> vec = {1, 2, 3};
vec.at(100); // throws instead of silent UB
std::array<int, 5> arr = {1, 2, 3, 4, 5};
arr.at(100);
Null checks
void foo(int* ptr) {
if (ptr == nullptr) {
std::cerr << "Null pointer\n";
return;
}
*ptr = 42;
}
Compiler warnings
g++ -Wall -Wextra -Werror main.cpp
Summary
Cause → mitigation
| Cause | Mitigation |
|---|---|
| Null pointer | Check nullptr |
| Dangling pointer | Smart pointers |
| Out of bounds | at(), careful indexing |
| Stack overflow | Heap allocation, fix recursion |
| Uninitialized | Initialize to nullptr |
| Double delete | Smart pointers |
Rules
- Prefer smart pointers over raw owning pointers.
- Check nullptr when the API allows null.
- Use
at()when bounds safety matters. - Enable ASan in development builds.
Checklist
- Check pointers before use?
- Use smart pointers for ownership?
- Validate array indices?
- Run with ASan in CI?
Related posts (internal)
- Undefined behavior
- Stack overflow
- shared_ptr vs unique_ptr
Keywords
Segmentation fault, SIGSEGV, Access Violation, null pointer, dangling pointer, AddressSanitizer
Practical tips
Debugging
- Use backtrace in GDB.
- Valgrind catches many memory errors.
- ASan gives fast, precise line numbers.
Performance
- nullptr checks are cheap.
- Smart pointers add small overhead;
unique_ptris usually negligible. at()is slightly slower thanoperator[]but safer when needed.
Code review
- Replace raw owning pointers with smart pointers.
- Flag dereferences without null checks.
- Watch array indexing in hot loops.
Closing
A segmentation fault means invalid memory access. Prefer smart pointers, explicit checks, and sanitizers during development.
Next: Deepen with smart pointers and undefined behavior.