Rust Using a Debugger
A debugger is a tool that pauses a running program on a marked line. Every value sits within reach while the program is paused.
Start the debugger
Build first. Then hand the debug binary to the starter command:
// in your terminal:
// $ cargo build
// $ rust-gdb target/debug/marksMark a line, then run
Inside the debugger you type short commands at its prompt. break marks the line. run starts the program:
// at the (gdb) prompt:
// break main
// runRead values while paused
print shows any value in reach, in its Rust shape. Ask for the inputs. Ask for the half-finished answer:
// at the (gdb) prompt:
// print scores
// print totalStep, do not leap
next runs one line and steps over calls. step runs one line and dives into a call. continue runs on to the next breakpoint:
// at the (gdb) prompt:
// next
// step
// continueThe editor drives the same session
The Debug label above main starts this same debugger inside your editor. Breakpoints become red dots in the margin. The values panel is print, without the typing:
fn main() {
let answer = sum_to(4);
println!("sum 1..=4 = {answer}");
}Example
fn sum_to(limit: i32) -> i32 {
let mut total = 0;
let mut n = 1;
while n <= limit {
total += n;
n += 1;
}
total
}
fn main() {
let answer = sum_to(4);
println!("sum 1..=4 = {answer}");
}Key points
- A debugger trades speed for sight: the program stops, and every value can be read.
- A breakpoint is a line that is marked: the running program pauses just before that line runs
- Use rust-gdb to start the gdb debugger on a Rust program.
- Use rust-lldb for the lldb debugger, the common one on macOS.
- Both starters load Rust pretty-printers.
- A Vec shows its items.
- A String shows its text.
- Neither shows raw memory.
- The everyday moves are few.
- run starts the program.
- next runs one line.
- step dives into a call.
- print shows a value.
- continue runs to the next breakpoint.
- Use a debug build for debugging.
- Its debug info maps the running program back to the source lines.
- An optimised build can report a value as optimised out.
In this example, sum_to adds the numbers from 1 up to the limit. A debugger session on it could go like this. Put a breakpoint on the total += n line. Run, and the program pauses with n = 1 and total = 0. Continue, and it pauses again with n = 2 and total = 1. Four pauses walk the loop by hand. The last one leaves total = 10, and main prints sum 1..=4 = 10.
Note
A debugger freezes time.
Some bugs hate being frozen and vanish.
If a bug hides whenever the program pauses, dbg! and logging are the better tools.
Prints never stop the clock.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
The debugger reports a key value as "optimised out". What went wrong?