GDB Cheatsheet

Watchpoints and Catchpoints

Use this GDB reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Watching a Value Change

A watchpoint stops the program when an expression's value changes, wherever that happens. Use it when you know what got corrupted but not where.

CommandStops when
watch exprthe program writes expr and the value actually changes
rwatch exprthe program reads expr
awatch exprthe program reads or writes expr
watch -l exprwatch the memory expr resolves to, ignoring scope
watch expr thread 3only when thread 3 changes it, hardware only
info watchpointslist them, same format as info breakpoints
(gdb) watch total
Hardware watchpoint 2: total

(gdb) continue
Hardware watchpoint 2: total
Old value = 0
New value = 42
add_row (n=42) at prog.c:31

Delete and disable use the same numbering space as breakpoints, so delete 2 and info b cover watchpoints too.

Hardware Versus Software Cost

gdb uses a hardware watchpoint when it can. x86 has four debug registers, each covering at most 8 bytes, so you get about four small watchpoints at once. Anything larger or more numerous falls back to software.

HardwareSoftware
MechanismCPU debug registersingle-step and re-test after every instruction
Speedfull program speedhundreds of times slower
Reported atthe exact instructionthe next statement after the change
Limit~4 regions of ≤8 bytes on x86-64unlimited
(gdb) watch big_struct
Hardware watchpoint 2: big_struct
(gdb) c
Continuing.
Could not insert hardware watchpoint 2.
Could not insert hardware breakpoints: You may have requested too many.

That message means you ran out of debug registers. Delete other watchpoints, or watch one field rather than the whole struct.

(gdb) watch cfg.timeout          # one field, fits a register
(gdb) set can-use-hw-watchpoints 0   # force software, slow but unlimited
(gdb) show can-use-hw-watchpoints

Addresses, Scope, and the Constant Trap

Watching a raw number does not work, because the number never changes. Cast and dereference it.

(gdb) watch 0x600850
Cannot watch constant value 0x600850.
(gdb) watch *(int *) 0x600850
Hardware watchpoint 1: *(int *) 6293584
(gdb) watch *(char (*)[16]) buf     # 16 bytes at buf

A watchpoint on a local variable is deleted automatically when its frame exits.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.

watch -l (long form -location) sidesteps that. It evaluates the expression once, takes the address, and watches that memory for the rest of the run. That is what you want for tracking a heap buffer that outlives the function that made it.

(gdb) watch -l node->key
(gdb) watch *global_ptr        # allowed before global_ptr is even set

Watching *p where p later changes watches the old object, since gdb re-evaluates the expression rather than the address. Use -l if you meant the original memory.

Catchpoints

A catchpoint stops on an event rather than a location. tcatch is the one-shot version.

CommandEvent
catch throwa C++ exception is thrown
catch throw std::bad_alloconly throws whose type matches the regex
catch rethrowan exception is re-thrown
catch catchan exception reaches a handler
catch execthe program calls exec
catch fork / catch vforkthe program forks
catch syscallany syscall, on entry and on return
catch syscall writeone syscall by name
catch syscall 257one syscall by number
catch syscall group:networka whole syscall group
catch load / catch unloada shared library loads or unloads, regex optional
catch signalany signal except SIGTRAP and SIGINT
catch signal SIGSEGV SIGBUSonly these signals
catch signal allincluding the ones gdb uses internally
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) r
Catchpoint 1 (exception thrown), 0x00007ffff7e9c0e2 in __cxa_throw ()
   from /lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
(gdb) up 4                  # climb out of libstdc++ into your own code

catch throw stops inside libstdc++, not in your code, so the first frames are runtime internals. Walk up until you reach a frame you recognize. The $_exception convenience variable holds the thrown object where the libstdc++ probes are present.

(gdb) catch catch std::runtime_error
(gdb) p $_exception
(gdb) catch syscall group:process
(gdb) catch load libplug

Signals

Catchpoints are one way to see a signal. handle is the other, and it controls whether the signal is passed on to the program at all.

(gdb) info signals
(gdb) handle SIGPIPE nostop noprint pass
(gdb) handle SIGUSR1 stop print
(gdb) signal SIGUSR1        # deliver one by hand
(gdb) signal 0              # resume without delivering the pending signal
KeywordMeaning
stop / nostopstop the program when the signal arrives
print / noprintannounce it at the prompt
pass / noignoredeliver it to the program
nopass / ignoreswallow it, the program never sees it

The usual case is a server using SIGPIPE or a timer using SIGALRM as normal flow control, which makes gdb stop constantly. handle SIGPIPE nostop noprint pass makes the session usable again. Unlike handle, a catchpoint can carry a condition and a commands block.