C++ Segmentation Fault: Causes, Debugging, and Prevention

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?
  2. Ten common causes
  3. Debugging
  4. Prevention
  5. Summary

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

CauseMitigation
Null pointerCheck nullptr
Dangling pointerSmart pointers
Out of boundsat(), careful indexing
Stack overflowHeap allocation, fix recursion
UninitializedInitialize to nullptr
Double deleteSmart pointers

Rules

  1. Prefer smart pointers over raw owning pointers.
  2. Check nullptr when the API allows null.
  3. Use at() when bounds safety matters.
  4. Enable ASan in development builds.

Checklist

  • Check pointers before use?
  • Use smart pointers for ownership?
  • Validate array indices?
  • Run with ASan in CI?

  • 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_ptr is usually negligible.
  • at() is slightly slower than operator[] 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.