Expert · Debugging and tools · topic 51 of 60 · 30 min
Debugging with gdb
Explanation
Prepare the program
gcc -std=c17 -Wall -Wextra -g -O0 bill.c -o bill # -g: debug info, -O0: no optimisation
gdb ./billThe essential commands
| Command | Short | Does |
|---|---|---|
| break main / break bill.c:42 | b | Stop at a function or a line |
| run [args] | r | Start the program (with arguments) |
| next | n | Run the current line, stepping OVER function calls |
| step | s | Run the current line, stepping INTO function calls |
| continue | c | Run until the next breakpoint |
| finish | fin | Run until the current function returns |
| print expr | p | Show a value: p total, p *order, p marks[3], p arr[0]@5 |
| info locals | i lo | Show all local variables |
| backtrace | bt | Show the call stack |
| frame N / up / down | f | Move between stack frames |
| watch expr | Stop when a variable's value changes | |
| list | l | Show source around the current line |
| quit | q | Exit gdb |
Finding a segfault
$ ./bill
Segmentation fault (core dumped)
$ gdb ./bill
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555189 in total_amount (items=0x0, n=3) at bill.c:8
8 sum += items[i].price;
(gdb) bt
#0 total_amount (items=0x0, n=3) at bill.c:8
#1 0x00005555555551d4 in print_bill (cart=0x7fffffffe010) at bill.c:21
#2 0x0000555555555210 in main () at bill.c:30
(gdb) frame 1
(gdb) print cart->items
$1 = (Item *) 0x0Watching a variable
(gdb) break main
(gdb) run
(gdb) watch balance # stop whenever balance changes
(gdb) continue
Hardware watchpoint 2: balance
Old value = 5000
New value = -200 # found the line that made it negativeCore dumps
A core dump is a snapshot of the program's memory at the moment it crashed. With core dumps enabled (ulimit -c unlimited in the shell; many Linux systems collect them with systemd-coredump and coredumpctl), you can run gdb ./bill core and type bt to investigate a crash that happened earlier, even on a test server.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Debugging with gdb · 1/6
In this lesson you will debug C programs with gdb.
Prefer a video by a teacher? Find free videos on “gdb tutorial debugging c segmentation fault backtrace breakpoints” on YouTube ↗
In real life: A crash in a payroll batch
A payroll batch job crashed only for one branch's data file. Running it under gdb with that file and typing bt showed the crash inside parse_employee called from load_branch; printing the line buffer revealed an empty department field, which made strchr return NULL that the code then dereferenced. A NULL check and a test for empty fields fixed it.
gdb --args ./payroll branch_17.csv
(gdb) run
(gdb) bt
(gdb) frame 1
(gdb) print linePractice (0/3 done)
Which gdb command shows the chain of function calls at a crash?
You want to go INTO the function called on the current line. Which command?
Write a program with a deliberate NULL-pointer crash three calls deep (main → load → parse). Compile with -g -O0, reproduce the crash in gdb, and use bt, frame, print and info locals to find the cause. Then set a breakpoint before the crash, step through, and use watch on a variable. Write down each command and what it showed.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Finding memory bugs with valgrindDebugging and tools · same module
- Sanitizers and warningsDebugging and tools · same module
- assert, logging and testing C codeDebugging and tools · same module
- Reading errors and debuggingJava Programming (Core to Spring Boot) · Control flow and methods
- Debugging like a pro: DevTools and VS CodeFrontend Web Development · Async JavaScript, modules and tools
- Building real projects: CMake, warnings, debuggers and sanitizersC++ Programming (modern C++ and DSA) · Exceptions, concurrency and building projects with CMake
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which flag adds debug information for gdb?
Answer: -g
Line numbers and variable names.
What does finish do?
Answer: Runs until the current function returns
Then shows the return value.
What does print arr[0]@5 show?
Answer: Five elements starting at arr[0]
@ prints an array slice.
Why debug with -O0 rather than -O2?
Answer: Optimised code reorders lines and removes variables, which is confusing to step through
Variables show <optimized out>.
What does "Step Into" do in a debugger?Related
Answer: Goes inside the method called on the current line
Step Into enters the called method.
Why print debug output to stderr rather than stdout?Related
Answer: stderr is unbuffered, so lines appear even if the program crashes right after
Buffered stdout may be lost on a crash.
You are paused on the line total = addGst(price); and want to see what happens inside addGst. Which button?Related
Answer: Step into
Step into goes inside the function called on this line. Step over would run it all and stop on the next line.
Which sanitizer finds use-after-free bugs?Related
Answer: AddressSanitizer
AddressSanitizer checks memory accesses.
From Building real projects: CMake, warnings, debuggers and sanitizers
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Debugging and tools” before its exam: Finding memory bugs with valgrind, Sanitizers and warnings, assert, logging and testing C code, A method for debugging.
- Module 11 exam: Debugging and tools · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Embedded C, system calls and careers. 60 topics left in the course before the final exam.