Segmentation Fault
Error Handling
Debugging
Programming
Software Development

Command failed due to signal Segmentation fault 11

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Segmentation fault: 11 means the process touched memory it is not allowed to access. The operating system stops the program immediately, so the visible message is short but the underlying bug can be complex. Effective diagnosis requires reproducible input, symbolized builds, and memory-focused tooling.

Reproduce the Crash Deterministically

Start by isolating one command and one input that always crashes.

bash
./my_tool --input sample.bin --mode validate
echo $?

If the crash is intermittent, capture exact flags, environment variables, and input hashes. A deterministic reproducer dramatically reduces debugging time and prevents false fixes.

Build with Debug Symbols and Sanitizers

Optimized stripped binaries hide useful context. Rebuild with debug information and address sanitizer:

bash
clang -g -O1 -fsanitize=address -fno-omit-frame-pointer main.c -o my_tool_asan
./my_tool_asan --input sample.bin

Address sanitizer reports many memory defects directly, including heap overflow, use-after-free, and double free. Use sanitizer output as primary evidence before speculative refactors.

Inspect Stack and State in a Debugger

If sanitizer output is not enough, use debugger backtrace and frame variables.

bash
1lldb -- ./my_tool --input sample.bin
2# run
3# bt
4# frame variable

Look for invalid pointers, out-of-range indexes, and corrupted container lengths near the first failing frame. Later frames often show secondary damage.

Check High-Probability Root Causes

Most segmentation faults in native code fall into repeatable categories:

  • Null pointer dereference.
  • Array or buffer index out of bounds.
  • Use-after-free from invalid object lifetime.
  • Writing through uninitialized pointer.
  • Data race corrupting shared memory.

Audit those paths first. A focused checklist is faster than broad code scanning.

Add Guard Conditions in Critical Paths

After root cause is found, add explicit bounds and null checks at risky boundaries.

c
1#include <stdio.h>
2
3int read_value(const int *arr, int len, int idx, int *out) {
4    if (!arr || !out) return -1;
5    if (idx < 0 || idx >= len) return -2;
6    *out = arr[idx];
7    return 0;
8}

Guards reduce crash risk and produce debuggable failure codes during invalid input conditions.

Preserve Crash Artifacts

For hard-to-reproduce failures, keep core dumps and symbol files from CI or staging.

bash
ulimit -c unlimited
./my_tool --input sample.bin
ls -lh core*

With matching symbols, postmortem analysis can continue even if original environment is gone.

Include Concurrency and FFI in Investigation

If your code uses threads or foreign function interfaces, expand investigation beyond local function logic. A race condition or invalid ownership transfer can surface as random segfault locations.

Thread sanitizer is useful for race detection:

bash
clang -g -O1 -fsanitize=thread main.c -o my_tool_tsan
./my_tool_tsan

For FFI boundaries, validate pointer ownership contracts in both caller and callee.

Prevent Regression with Targeted Tests

Add tests for the exact input that caused the crash and nearby boundary cases. A fix without regression tests is likely to reappear under different data.

c
// pseudo test intent
// input length 0 should return error, not crash
// invalid index should return error code

Also enable compiler warnings and treat critical warnings as errors in CI where feasible.

Practical Incident Workflow

A reliable workflow for production incidents:

  1. Capture crash command and input metadata.
  2. Reproduce locally with symbols.
  3. Run sanitizer build.
  4. Confirm root cause with debugger.
  5. Patch with guard and ownership fix.
  6. Add regression tests and deploy with monitoring.

This sequence keeps debugging disciplined and reduces time spent on guesswork.

Common Pitfalls

  • Debugging a non-reproducible command and changing many variables at once.
  • Investigating only optimized binaries with no symbols.
  • Ignoring sanitizer diagnostics and chasing unrelated code paths.
  • Fixing one crashing line without repairing ownership or bounds logic.
  • Merging a fix without regression tests for the failing input.

Summary

  • Segmentation fault 11 indicates invalid memory access, not one specific bug.
  • Reproducible input is the foundation of efficient debugging.
  • Use sanitizer builds and debugger traces for direct evidence.
  • Focus first on common memory safety categories.
  • Add targeted tests and guardrails so the crash does not return.

Course illustration
Course illustration

All Rights Reserved.