During a systems-focused project in grad school, I once spent close to an hour "fixing" a C++ segfault by staring at the line the program happened to crash on and guessing what might be wrong with it — before a classmate pointed out I hadn't actually looked at the backtrace yet. That hour taught me more about how not to debug memory bugs than anything since.

A segmentation fault means the program touched memory it didn't have permission to touch, and the line where the crash message points is often just where the invalid access finally got caught — not necessarily where the actual mistake happened. Running the program under gdb (or lldb on macOS) and typing bt the moment it crashes gives you the real call stack: which function was running, and which functions called it to get there.

That backtrace is where the useful information actually lives. If the crash happens deep inside a standard library container, the backtrace shows you the exact line in your own code that called into it with bad data, instead of leaving you staring at a crash inside code you didn't write and don't control.

For a specific and very common category — reading or writing memory that's already been freed, or writing past the end of an allocated buffer — AddressSanitizer (ASan) is worth reaching for before gdb, not after. Compile with -fsanitize=address, run the program normally, and ASan will halt execution at the exact instruction that corrupted memory, with a report showing both where the bad access happened and, often, where the memory was originally allocated and freed.

That combination — gdb or lldb for "where was I when this crashed," ASan for "what memory operation actually caused the corruption" — covers the two different questions a segfault raises, and answers both with real evidence instead of a guess based on which line the crash message happened to land on.

Both tools are documented in depth by their own projects — GDB's manual on sourceware.org, LLDB's on lldb.llvm.org, and AddressSanitizer's usage docs in the LLVM project's own documentation — well past what a debugging session usually needs, but worth knowing exists once the basics stop being enough.