GDB Cheatsheet
Inspecting Data
Use this GDB reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
print and Formats
print is p. A slash plus a format letter overrides how the value is rendered,
without changing its type.
| Format | Prints as | Example |
|---|---|---|
/x | hexadecimal | p/x 255 → 0xff |
/d | signed decimal | p/d 0xff → 255 |
/u | unsigned decimal | p/u -1 → 4294967295 |
/o | octal | p/o 8 → 010 |
/t | binary, t for "two" | p/t 5 → 101 |
/c | integer plus character constant | p/c 65 → 65 'A' |
/f | reinterpret the bits as floating point | p/f 1078530011 |
/a | address plus nearest preceding symbol | p/a $pc |
/s | treat as a null-terminated string | p/s buf |
/z | hex, zero-padded to the type's width | p/z (char)5 → 0x05 |
/r | raw, bypass any Python pretty-printer | p/r vec |
(gdb) p total $1 = 42 (gdb) p/x total $2 = 0x2a (gdb) p $1 + 1 # value history, every result is numbered $3 = 43 (gdb) p $ # the last value (gdb) p $$2 # two results back
Every result goes into the value history as $N, so you never have to retype a
long expression. $ is the last one and $$ the one before it.
Arrays, Structs, and Pointers
A pointer prints as an address, so gdb has no idea how many elements follow it.
The @ artificial-array operator supplies the length. This is the single most
forgotten piece of gdb syntax.
(gdb) p arr # a real array knows its own length $1 = {3, 1, 4, 1, 5} (gdb) p ap # a pointer does not $2 = (int *) 0x555555558010 (gdb) p *ap@5 # 5 elements starting at *ap $3 = {3, 1, 4, 1, 5} (gdb) p *ap@n # the length can be a variable (gdb) p arr[2]@3 # a slice starting mid-array $4 = {4, 1, 5} (gdb) p *node->items@node->len
(gdb) set print pretty on (gdb) p cfg $5 = { name = 0x555555556004 "api", port = 8080, flags = 6 } (gdb) p cfg.name (gdb) p *nodep (gdb) p nodep->next->next->key (gdb) p (char *) buf (gdb) p (struct row *) 0x555555558010
| Setting | Effect |
|---|---|
set print pretty on | one struct member per line, indented |
set print union off | do not expand unions inside structs |
set print array on | one array element per line |
set print array-indexes on | label each element with its index |
set print elements 0 | print full arrays and strings, no ... truncation |
set print repeats 0 | do not collapse <repeats 40 times> |
set print null-stop on | stop char arrays at the first NUL |
set print max-depth 3 | replace deeper nesting with ellipsis |
set print object on | use a C++ object's dynamic type, not the declared one |
set print static-members off | hide static members of C++ classes |
set print elements 0 is what you want the first time a long buffer prints as
"aaaa".... The default cap is 200 elements.
Types
| Command | Shows |
|---|---|
whatis expr | the declared type, one level, no expansion |
ptype expr | the full type definition, expanded |
ptype/o struct row | plus byte offsets and holes, gdb 8.1 and later |
ptype/x | struct sizes and offsets in hex |
info types row | every type whose name matches |
info line parse.c:42 | which addresses that line compiles to |
info scope parse_row | every symbol in that scope and where it lives |
(gdb) whatis cfg type = struct config (gdb) ptype cfg type = struct config { char *name; int port; unsigned int flags; } (gdb) ptype/o struct config /* offset | size */ type = struct config { /* 0 | 8 */ char *name; /* 8 | 4 */ int port; /* 12 | 4 */ unsigned int flags; /* total size (bytes): 16 */ }
ptype/o is how you find the padding that made a struct bigger than the sum of
its fields. whatis stops at one level, so whatis on a typedef gives you the
typedef name and ptype gives you what it resolves to.
Watching, Setting, and Calling
| Command | Effect |
|---|---|
display expr | print expr after every stop |
display/x expr | with a format |
display/3i $pc | the classic, three upcoming instructions each stop |
info display | list them |
undisplay N / delete display N | remove one |
set var x = 5 | assign to a program variable |
print x = 5 | same assignment, and prints the result |
call f(1, 2) | run a function in the inferior, print non-void results |
print f(1, 2) | same, but always prints even a void result |
(gdb) display total 1: total = 42 (gdb) display/x flags (gdb) set var retries = 0 # force the loop to exit (gdb) set var node->next = 0 (gdb) call dump_table(t) (gdb) p strlen(name) $6 = 3
Use set var x = 1, not set x = 1. Bare set first tries to match a gdb
setting, so a variable called width or listsize would silently change gdb's
own configuration instead of your program. set var never does that.
Calling into the inferior runs real code, which can allocate, take locks, or crash.
If the called function hits a breakpoint, gdb stops inside it and leaves a dummy
frame on the stack. set unwind-on-signal on makes gdb undo the call if it faults.
Convenience Variables and Registers
Convenience variables live in gdb, not in the program, and they start out void
so you can use them as scratch space.
(gdb) set $p = nodep (gdb) while $p != 0 >p $p->key >set $p = $p->next >end (gdb) p $rsp (gdb) p $pc (gdb) p/x $rax (gdb) p $_exitcode (gdb) p $_siginfo.si_signo (gdb) info args
| Variable | Holds |
|---|---|
$pc / $sp / $fp | program counter, stack pointer, frame pointer |
$rax $rdi $rsi $rsp $rip | x86-64 registers by name |
$N, $, $$, $$N | value history entries |
$_ / $__ | last address examined by x, and its contents |
$_exitcode | exit status after the program finishes |
$_siginfo | the signal that stopped the program |
$_thread / $_gthread | current thread number, per-inferior and global |
$_probe_argN | argument N of a SystemTap probe stop |
C++ Pretty Printers
A gdb built with Python and a GCC installation ships printers for std::string,
std::vector, std::map, and the rest, so containers print as their contents.
(gdb) p names $1 = std::vector of length 3, capacity 4 = {"a", "bb", "ccc"} (gdb) p m $2 = std::map with 2 elements = {["k"] = 1, ["z"] = 9} (gdb) info pretty-printer (gdb) p/r names # raw internals instead (gdb) disable pretty-printer global libstdc++
If containers print as raw _M_impl internals, the printers are not loaded. They
come from libstdcxx python files that GCC installs, and gdb loads them through
an auto-load script next to libstdc++.so, so set auto-load safe-path and
add-auto-load-safe-path control whether they run. info auto-load python-scripts
tells you which were loaded and which were denied.