Core Dump Analysis - When Production Explodes
Your Rust app crashed in production at 3am with this helpful error from your production monitoring:
[1] 2837 segmentation fault (core dumped) ./myapp
No stack trace. No panic message. Just a dead process and a 500MB core dump. This is when rust-gdb earns its keep:

ulimit -c unlimited # Before running in prod
rust-gdb ./target/release/myapp core.2837
Real example: A web service was crashing randomly in production. The core dump showed a HashMap<UserId, Connection>
where one of the Connection structs had a null pointer in an Arc<TcpStream>
. Without rust-gdb, we would have seen raw memory addresses. With it, we could see which user ID was associated with the bad connection.
The fix took 10 minutes once we saw the data. Finding it without rust-gdb would have taken weeks.
Memory Corruption in Unsafe Code
Rust's memory safety goes out the window when you use `unsafe`. rust-gdb is essential for debugging these unsafe code issues:
unsafe {
// This code looks innocent but corrupts memory
let ptr = self.buffer.as_mut_ptr().add(offset);
*ptr = value; // offset was calculated wrong
}
Standard debugging tools show you assembly and register dumps. rust-gdb shows you the actual Rust data structures being corrupted. You can see:
- Which
Vec
had its length corrupted
- What the
Box
was pointing to before it got freed twice
- The actual contents of your unsafe data structures
FFI Boundary Debugging
When Rust talks to C code via FFI, shit breaks in creative ways. I once debugged a crash where a C library was writing past the end of a buffer we allocated using unsafe memory operations:
let mut buffer = vec![0u8; 1024];
unsafe {
// C code writes 1025 bytes, corrupting Vec metadata
c_function(buffer.as_mut_ptr(), buffer.len());
}
rust-gdb showed that the Vec's capacity field was overwritten with garbage. Regular GDB would show "some memory changed." rust-gdb showed exactly which Rust type was corrupted and how.
The .gdbinit That Actually Works
Skip the academic examples. Here's a .gdbinit that works for real debugging:
## Don't paginate output (you're piping to files anyway)
set pagination off
set confirm off
## Show actual array contents, not just pointers
set print pretty on
set print array on
set print array-indexes on
## Rust-specific: disable pretty-printing for large types
## (they crash the debugger)
define disable_heavy_printers
disable pretty-printer global Vec
disable pretty-printer global HashMap
disable pretty-printer global BTreeMap
end
## Auto-load this when debugging large programs
## You can re-enable with `enable pretty-printer global Vec`
Theoretical advice: "Use conditional breakpoints to isolate hot paths."
Reality: Conditional breakpoints slow your program to a crawl. Better approach:
- Profile first with
cargo flamegraph
- Identify the hot function (not line)
- Add strategic prints to that function
- Use rust-gdb only for data structure inspection
Example: Our HTTP server was slow. Profiling showed 60% of time in parse_headers()
. Instead of setting 50 conditional breakpoints, we added one print statement showing the request size. Turns out clients were sending 50MB headers (malformed requests). One fix, massive performance improvement.
Async Debugging Horror Stories
Async Rust debugging is where rust-gdb shows its limitations. Futures are state machines, and GDB doesn't understand state machines:
(gdb) p my_future
$1 = Future<Output = Result<Response, Error>> = {
state: 2, # What does state 2 mean?
data: 0x7fff8badf000 # Points to... what?
}
Better approach: Use tokio-console for async debugging. rust-gdb is better for post-mortem analysis of async code that crashed.

Multi-threaded Nightmare Debugging
Race conditions are the worst bugs to debug. rust-gdb can help, but it's not magic:
## See all threads
info threads
## Look at all stack traces simultaneously
thread apply all bt
## This usually shows 12 threads all waiting on the same mutex
## The real bug is usually in thread 1
Pro tip: That "race condition" you're chasing? It's probably a deadlock. Look for circular lock dependencies in Rust:
- Thread 1: locks A, wants B
- Thread 2: locks B, wants A
rust-gdb can show you which mutexes are locked, but understanding the dependency requires reading code. If you're dealing with more complex threading issues, you'll need to understand lock dependencies - but that's beyond what rust-gdb can help with.
When rust-gdb Saves Your Job
Core dump from production showing memory corruption in a financial system. Money is disappearing. Everything is on fire. rust-gdb showed that a Decimal
type was being zeroed by a buffer overflow in adjacent memory.
The bug was in unsafe code that calculated memory offsets wrong. Without rust-gdb showing the exact Rust types being corrupted, we never would have found it. With rust-gdb, the fix took 2 hours instead of 2 weeks.
That's when rust-gdb is worth learning.
The truth is, rust-gdb is a specialized tool for specialized situations. 99% of the time, you'll be fine with println! debugging and your IDE. But when you hit that 1% case - production crashes, memory corruption, or embedded debugging where you need to see both the hardware state and Rust types - nothing else comes close.
If you've made it this far, you probably have one of those 1% problems. Here are the resources that will actually help you solve it.