Logo

What is a segmentation fault in C and C++?

A segmentation fault (often shortened to “segfault”) is a specific kind of runtime error that occurs when a program attempts to access memory it’s not allowed to, or in a way that violates the operating system’s memory protection rules. C and C++ (being low-level, memory-manipulating languages) frequently encounter segmentation faults if pointers or array indices are used incorrectly.

Common Causes of Segmentation Faults

  1. Dereferencing Null or Uninitialized Pointers

    • Example:
      int *p = NULL; *p = 10; // Segfault: p points to invalid memory
    • Another scenario is when a pointer hasn’t been assigned at all (uninitialized local pointer variables), leading to random addresses.
  2. Out-of-Bounds Array Access

    • Example:
      int arr[5]; arr[10] = 42; // Writing past the valid index range of 0..4
    • Reading or writing beyond the array’s allocated size leads to unpredictable behavior. Sometimes it causes a segfault immediately; other times it may silently corrupt memory.
  3. Using Freed or Deleted Memory (Dangling Pointers)

    • Example:
      int *ptr = malloc(sizeof(int)); free(ptr); *ptr = 5; // Segfault: ptr references memory that is no longer valid
    • In C++, similarly, calling delete on a pointer and then using it again is undefined behavior.
  4. Misuse of Stack or Heap

    • Writing very large local arrays can overflow the stack.
    • Incorrectly managing malloc/free, new/delete, or ignoring error checks on memory allocations can cause memory corruption or segfaults.

How Segmentation Faults Occur Internally

  1. Memory Protection: Modern operating systems and CPUs typically mark specific memory regions as “read-only,” “read-write,” or “no access.”
  2. Invalid Access: When your program attempts to read or write to a region of memory it doesn’t own—like a pointer pointing to an arbitrary location or an out-of-bounds array index—the hardware raises an exception.
  3. Signal Handling: In Unix-like systems, this is delivered as a SIGSEGV (signal 11) to the process. By default, the OS kills the process and dumps core (if enabled).

Diagnosing and Preventing Segfaults

  1. Check Pointers

    • Initialize pointers before use (e.g., nullptr in C++ or NULL in C).
    • Verify memory allocation returns a valid pointer.
    • Avoid dangling pointers by setting them to NULL after free or delete if you must keep them around (though it’s better to keep pointer lifetimes clear and scoped in C++ with smart pointers).
  2. Bounds Checking

    • Always ensure array or pointer arithmetic remains within valid ranges.
    • In debugging or safe languages, you might have array-bound checks automatically, but in C/C++, you must handle them manually.
  3. Use Debugging Tools

    • GDB or LLDB: Step through code, set breakpoints, examine the call stack, see exactly where the segfault happened.
    • Valgrind or AddressSanitizer: Check for memory leaks, out-of-bounds writes, use-after-free scenarios.
  4. Adopt Safer Practices

    • Where possible, use higher-level abstractions (e.g., std::vector in C++ instead of raw arrays) that perform boundary checks or manage memory automatically.
    • In modern C++, consider smart pointers (std::unique_ptr, std::shared_ptr) to reduce manual memory management errors.

Example

#include <stdio.h> #include <stdlib.h> int main(void) { int *arr = (int *)malloc(sizeof(int) * 5); if (!arr) { // Allocation failed return 1; } // Incorrectly writing beyond allocated space for (int i = 0; i < 10; i++) { // 10 is out of bounds arr[i] = i; } free(arr); return 0; }
  • The loop runs from i = 0 to 9, but arr was only allocated space for 5 elements, i.e., arr[0]..arr[4].
  • This out-of-bounds access can cause a segmentation fault, memory corruption, or other undefined behavior.

Core Dump & Debugging

  • When a program segfaults, some systems create a core dump: a snapshot of the program’s memory at the time of the crash.
  • Tools like GDB can load the core dump to pinpoint the instruction where the program crashed and examine variable states, which is invaluable for debugging.

Final Thoughts

Segmentation faults in C and C++ arise when you stray outside valid memory—often due to pointer mismanagement or array bounds errors. They’re one of the main pitfalls of these low-level languages, which give you power but also responsibility over memory. Writing robust, safe C/C++ code requires disciplined pointer usage, thorough testing, and, where possible, the adoption of safer abstractions.

Strengthen Your Memory & Pointer Expertise

If you want to solidify your grasp of C/C++ memory management and data structures—and prepare for coding interviews—two recommended courses from DesignGurus.io are:

  1. Grokking Data Structures & Algorithms for Coding Interviews
    Delve into arrays, linked lists, graphs, and more, all with a focus on robust coding practices.

  2. Grokking the Coding Interview: Patterns for Coding Questions
    Master the coding patterns that frequently appear in technical interviews, enabling you to craft solutions systematically and safely.

By understanding segmentation faults, you’ll write more reliable C/C++ programs and quickly debug any memory-related errors you encounter.

CONTRIBUTOR
TechGrind