C β€” Debugging with GDB
C β€” Debugging with GDB

C β€” Debugging with GDB

Created on:
Team Size: 1
Tool Used: C/GCC/GDB

GDB (GNU Debugger) lets you run a C program step by step, inspect memory and variables at any point, and find exactly where and why something goes wrong.

Step 1 β€” Compile with Debug Symbols

By default GCC strips debug information from the binary. The -g flag includes it:

gcc -Wall -Wextra -Werror -g main.c -o my_program

Without -g, GDB can still run the program but cannot show source lines, variable names, or meaningful stack frames β€” just raw addresses.

Step 2 β€” Launch GDB

gdb ./my_program

This opens the GDB prompt (gdb). The program is loaded but not yet running.

If your program takes command-line arguments, use --args so GDB does not consume them:

gdb --args ./my_program arg1 arg2

Everything after the binary name is forwarded to your program when you run r. Without --args, passing arguments directly to gdb would be interpreted as GDB options.

Step 3 β€” Use GDB TUI for a Visual Layout

gdbtui launches GDB with a split-screen terminal UI β€” source code on top, command prompt below. It is far easier to follow than the plain prompt:

gdbtui ./my_program
gdbtui --args ./my_program arg1 arg2   # with arguments

The top pane shows the source file with an arrow pointing at the current line. The bottom pane is the normal GDB command prompt.

Core Commands

r β€” Run

Starts (or restarts) the program. Pass arguments after r if your program expects them:

(gdb) r
(gdb) r arg1 arg2

The program runs until it hits a breakpoint, crashes, or finishes.

b β€” Breakpoint

Pauses execution before a specific line or function:

(gdb) b 42          # break at line 42 of the current file
(gdb) b main.c:15   # break at line 15 of main.c
(gdb) b my_function # break at the entry of my_function

List all breakpoints:

(gdb) info b

Delete a breakpoint by its number:

(gdb) delete 1

n β€” Next (step over)

Executes the current line and moves to the next one. If the current line is a function call, the entire function runs without stepping into it:

(gdb) n

s β€” Step (step into)

Like n, but if the current line calls a function, GDB steps inside that function:

(gdb) s

Use s when you want to follow execution into a function you wrote. Use n when you want to skip over library calls or functions you trust.

c β€” Continue

Resumes execution at full speed until the next breakpoint (or the end of the program):

(gdb) c

Evaluates and prints any expression β€” variable, pointer, arithmetic:

(gdb) print x
(gdb) print *ptr
(gdb) print arr[2]
(gdb) print a + b

You can also modify a variable on the fly:

(gdb) print x = 10

disp β€” Display (auto-print on every step)

display works like print but re-evaluates and shows the value automatically after every n, s, or c that pauses execution:

(gdb) disp x
(gdb) disp *ptr
(gdb) disp arr[i]

List active displays:

(gdb) info display

Remove a display by its number:

(gdb) undisplay 1

Useful Extra Commands

bt β€” Backtrace

Shows the full call stack at the current point β€” essential when diagnosing a crash:

(gdb) bt
#0  ft_strlen (s=0x0) at ft_strlen.c:6
#1  ft_putstr (str=0x0) at ft_putstr.c:12
#2  main () at main.c:20

Read from bottom to top: main called ft_putstr which called ft_strlen where the crash occurred.

p/x β€” Print in Hexadecimal

Useful for inspecting raw memory values, addresses, and bitfields:

(gdb) p/x flags
(gdb) p/x *ptr

watch β€” Watchpoint

Pauses execution whenever a variable’s value changes β€” useful for tracking down unexpected mutations:

(gdb) watch x

refresh β€” Redraw the TUI

The TUI pane can glitch after terminal output or resizing. refresh (or its shorthand ref) redraws it cleanly:

(gdb) refresh
(gdb) ref

Run it any time the source window looks garbled.

q β€” Quit

(gdb) q

A Typical Session

# Compile with debug symbols
gcc -Wall -Wextra -Werror -g main.c utils.c -o my_program

# Launch with TUI (with optional arguments)
gdbtui --args ./my_program arg1 arg2
(gdb) b main          # break at entry
(gdb) r               # run until breakpoint
(gdb) disp i          # watch variable i on every step
(gdb) disp *ptr       # watch what ptr points to
(gdb) n               # step over next line
(gdb) s               # step into the function call
(gdb) print result    # inspect a value
(gdb) c               # continue to next breakpoint
(gdb) bt              # check the call stack after a crash
(gdb) q               # quit

Quick Reference

CommandEffect
gcc -ginclude debug symbols in the binary
gdbtui ./proglaunch GDB with split source/command UI
gdb --args ./prog a bpass arguments to the program, not to GDB
rrun (or restart) the program
b <line>set a breakpoint at a line or function
nnext line β€” step over function calls
sstep β€” enter function calls
ccontinue until next breakpoint
print <expr>evaluate and print an expression once
disp <expr>auto-print an expression after every step
btshow the full call stack
p/x <expr>print value in hexadecimal
watch <var>pause when a variable changes
refresh / refredraw the TUI when it glitches
qquit GDB
© 2026 Samuel Styles