# The interactive debugger This chapter covers `perl -d`: launching a program under the debugger, the prompt, the essential motion and inspection commands, and the stack-navigation vocabulary. After this chapter you can investigate any running program interactively. Readers start from knowing `print` / `warn` work but are not enough: you need to stop, look around, peek at variables, walk the call stack, then resume. That is what this chapter delivers. ## Launching For any script `app.pl`, prepend `-d`: ``` perl -d app.pl --verbose input.txt ``` Arguments after the script name pass to the script as normal. Common launch forms: | Form | Purpose | |----------------------------|-------------------------------------| | `perl -d script.pl args` | Debug the given script. | | `perl -d -e 'CODE'` | Debug a one-liner expression. | | `perl -de 0` | Interactive REPL sandbox. | | `perl -d:Module script.pl` | Load `Devel::Module` as debugger. | | `perl -d:NYTProf script` | Profile via NYTProf plugin. | | `perl -S -d script.pl` | Search `$PATH` for the script. | `-d` causes the compiler to emit per-statement hook points; the interpreter preloads `perl5db.pl` before the first runtime line. Never pipe input to `perl -d` and never use `/dev/stdin` — the debugger needs a TTY to read commands from. Launch from a real terminal. ## The prompt ``` Loading DB routines from perl5db.pl version 1.77 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(app.pl:4): my $key = 'welcome'; DB<1> ``` The line `main::(app.pl:4):` shows the next line **about to execute** — nothing in the program has run yet. Compile-time code (`BEGIN`, `use`) already ran; the first prompt comes before the first runtime statement. `DB<1>` — the number is a command counter that increments on each command. `!N` recalls command number N. `DB<>` with double brackets means you are inside a nested debugger (one expression you stepped into called another breakable expression). The debugger always shows the line about to execute, never the line just executed. ## Quitting ``` DB<1> q ``` Not `quit`, not `exit`. Typing `exit` runs Perl's [`exit`](../../p5/core/perlfunc/exit) inside the debugger's `eval`, which is not the same. `^D` at the prompt works on most terminals. ## Help ``` DB<1> h # one-screen summary DB<1> h h # full help (long — use the pager) DB<1> h b # help on one command DB<1> |h h # pipe full help through $ENV{PAGER} ``` ## Where am I? `v` views a window around the current line. `l` lists a specified range: ``` DB<1> v 1 #!/usr/bin/perl 2 use v5.40; 3 4==> my $key = 'welcome'; 5: my %data = ( 6 'this' => qw(that), 7 'tom' => qw(and jerry), 8 'welcome' => q(Hello World), 9 'zip' => q(welcome), 10 ); ``` - `==>` marks the next line to execute. - `:` marks executable lines — you can set a breakpoint there. - Lines without `:` are not breakable (comments, blanks, continuations of a multi-line statement). Navigation: | Command | Effect | |---------------|--------| | `v` | View a window around the current line. | | `v LINE` | View a window around LINE. | | `l` | List the next window; repeat advances. | | `l LINE` | List just LINE. | | `l MIN-MAX` | List a range. | | `l SUB` | List the first window of SUB. | | `-` | Previous window. | | `.` | Snap view back to the current line. | | `f FILE` | Switch display to FILE (regex against `%INC`). | | `/PAT/` | Forward search in source. | | `?PAT?` | Backward search. | ## Motion: `s`, `n`, Enter, `c`, `r` The four essential motion commands: | Command | Effect | |-------------|--------| | `s` | Step — execute next statement; descend into subroutines. | | `n` | Next — execute next statement; step over subroutines. | | `` | Repeat the last `s` or `n`. | | `c` | Continue until next breakpoint or end. | | `c LINE` | Continue to a one-shot breakpoint at LINE, then stop. | | `c SUB` | Continue to the first line of SUB. | | `r` | Return from the current sub; stop at the caller. | ``` DB<1> s # descend into the call DB<2> n # stay at this level DB<3> # repeats the last motion DB<4> c 42 # run to line 42 once DB<5> r # pop the current frame ``` A multi-line statement steps atomically — one `s` executes a whole multi-line hash assignment. On a line that calls no subroutines, `s` and `n` are indistinguishable. ## Printing values: `p` and `x` ``` DB<1> p $key welcome DB<2> p join ',', sort keys %data this,tom,welcome,zip ``` `p EXPR` evaluates EXPR in the program's current package and prints the scalar-context result followed by a newline. `p` is flat — for a reference it prints `HASH(0x...)`, not contents. For structures, use `x`: ``` DB<3> x \%data 0 HASH(0x5651f9a82358) 'this' => 'that' 'tom' => 'and' 'welcome' => 'jerry' 'zip' => 'Hello World' ``` Always pass a **reference** (`x \%h`, `x \@a`) — `x %h` dumps the flat key/value list, which hides the structure. See [inspecting-state](inspecting-state) for the full inspection vocabulary (`V`, `X`, `y`, `m`, `M`, `i`, depth controls). ## The call stack: `T`, `s`, `r` `T` prints a backtrace — the chain of sub calls that led to the current line: ``` DB<1> T $ = main::handle_request(ref(HTTP::Request)) called from file 'app.pl' line 47 $ = main::dispatch('GET', '/users/42') called from file 'app.pl' line 19 @ = main::main() called from file 'app.pl' line 12 ``` - `$` — called in scalar context. - `@` — called in list context. - `.` — void context. - Arguments are shown with `Data::Dumper`-style truncation; the exact length cap is the `maxTraceLen` option. Navigate the stack with `s` (into a call) and `r` (out of the current frame). There is no "frame up / frame down" command: re-step if you go too deep, or use `b` to set a breakpoint at the caller and `c` to reach it. To inspect an outer frame's lexicals, use `y LEVEL` from [inspecting-state](inspecting-state) — it reads via `PadWalker` and shows the enclosing scope's `my` variables. ## Evaluating Perl at the prompt Anything the debugger does not recognise as a command is `eval`'d as Perl code in package `DB` at the current lexical scope: ``` DB<1> $counter = 0 # mutate state DB<2> @ARGV = qw(new args) # mutate @ARGV DB<3> $obj->reset # call a method DB<4> m/(\w+)/ && p $1 # match against $_ ``` A fresh `my $x` at the prompt vanishes when the command returns — the prompt has its own lexical scope. Use a bareword, `our`, or chain on one line: ``` DB<1> our $tmp = compute(); # survives DB<2> $tmp = compute(); p $tmp # one-line chain ``` Force Perl interpretation when an expression looks like a debugger command: ``` DB<1> ; h EXPR # ; prefix forces eval DB<2> + h EXPR # + prefix works too ``` ## Restart and rerun `R` restarts the program via `exec()`. History, breakpoints, actions, options, and the command line are preserved: ``` DB<1> R ``` `rerun` re-executes without leaving the debugger, preserving state: | Form | Effect | |------------|-------------------------------------------| | `rerun` | Restart, replaying no prior commands. | | `rerun -N` | Restart and replay up to N commands back. | | `rerun N` | Restart from history entry N. | ## Redefining a sub mid-session Paste the entire `sub NAME { ... }` at the prompt. Or edit a replacement file and load it: ``` DB<1> do 'fixed.pl' ``` Subsequent calls use the new definition. Existing stack frames continue with the old body. ## Commands so far | Command | Effect | |---------------------|--------| | `h`, `h CMD`, `h h` | Help: summary / one command / full. | | `\|CMD` | Pipe the output through `$ENV{PAGER}`. | | `q` | Quit. | | `v`, `v LINE` | View source around current / LINE. | | `l`, `l LINE`, `l SUB`, `l MIN-MAX` | List. | | `.` | Snap to current line. | | `-` | Previous window. | | `f FILE` | Switch display to FILE. | | `/PAT/`, `?PAT?` | Search forward / backward. | | `s` | Step into. | | `n` | Step over. | | `` | Repeat last `s` / `n`. | | `r` | Return from current sub. | | `c`, `c LINE`, `c SUB` | Continue / one-shot breakpoint. | | `p EXPR` | Print (scalar context). | | `x EXPR` | Dump (structured, pass a reference). | | `T` | Stack backtrace. | | `R` | Restart via `exec()`. | | `rerun [N\|-N]` | Restart with history replay. | ## Find out more - [breakpoints](breakpoints) — `b`, conditionals, actions, watches, timing matrix. - [inspecting-state](inspecting-state) — `V`, `X`, `y`, `m`, `M`, `i`, depth controls. - [tracing](tracing) — `t`, `AutoTrace`, line-info output to a file.