Introduction
Debugging is a critical skill for any systems programmer working with C or C++. Unlike higher-level languages, C and C++ give you direct access to memory and low-level operations, which makes debugging both powerful and complex. The GNU Debugger (GDB) is one of the most widely used tools for debugging C and C++ programs.
What is GDB?
GDB (GNU Debugger) is a command-line debugging tool used to inspect and control the execution of programs. It allows developers to:
- Pause execution (breakpoints)
- Step through code line-by-line
- Inspect variables and memory
- Modify program state at runtime
- Analyze crashes and core dumps
GDB works by interfacing with compiled binaries that include debugging symbols.
Installing GDB
Linux (Ubuntu/Debian)
sudo apt update
sudo apt install gdb
macOS (with Homebrew)
brew install gdb
Windows
Use MinGW or WSL:
- Install WSL and Ubuntu
- Then install GDB inside WSL
Compiling with Debug Symbols
To use GDB effectively, you must compile your program with debug information using the -g flag:
gcc -g program.c -o program
g++ -g program.cpp -o program
Optional flags:
-
-O0→ disable optimization (recommended for debugging) -
-Wall→ show warnings
Example:
gcc -g -O0 -Wall main.c -o main
Starting GDB
gdb ./program
Once inside GDB:
(gdb)
Running the Program
run
With arguments:
run arg1 arg2
Breakpoints
Set breakpoint at function
break main
Set breakpoint at line
break 10
Set breakpoint in file
break file.c:25
List breakpoints
info breakpoints
Delete breakpoint
delete 1
Stepping Through Code
Step into (enter functions)
step
Step over (skip function internals)
next
Continue execution
continue
Finish current function
finish
Inspecting Variables
Print variable
print x
Print pointer value
print *ptr
Display automatically
display x
Show all local variables
info locals
Working with Memory
Examine memory
x/4x ptr
Format explanation:
-
4→ number of units -
x→ hexadecimal format
Examples:
x/10d ptr # decimal
x/5c ptr # characters
Call Stack (Backtrace)
When a crash occurs:
backtrace
This shows the function call chain.
Navigate stack:
frame 0
frame 1
Watchpoints
Watchpoints track variable changes.
watch x
Breaks when x changes.
Conditional Breakpoints
break 20 if x == 5
Modifying Variables
set variable x = 10
Debugging Segmentation Faults
Compile with -g, then run:
gdb ./program
run
When it crashes:
backtrace
Check variables:
print ptr
Common causes:
- Null pointer dereference
- Out-of-bounds array access
- Use-after-free
Core Dumps
Enable core dumps:
ulimit -c unlimited
Run program → crash generates core file.
Analyze:
gdb program core
Debugging Multi-file Projects
Compile all files with -g:
gcc -g main.c utils.c -o app
Then debug normally.
Working with C++ in GDB
GDB supports:
- Classes
- Objects
- Templates
- STL containers (with limitations)
Print object:
print obj
Pretty printing (for STL):
set print pretty on
Advanced Features
1. TUI Mode (Text UI)
gdb -tui ./program
2. Layout Commands
layout src
layout asm
3. Disassembly
disassemble main
4. Reverse Debugging (if supported)
reverse-continue
Useful GDB Shortcuts
| Command | Description |
|---|---|
| r | run |
| c | continue |
| n | next |
| s | step |
| bt | backtrace |
| p |
Example Debugging Session
Code (buggy)
#include <stdio.h>
int main() {
int *ptr = NULL;
printf("%d\n", *ptr);
return 0;
}
Steps
gcc -g main.c -o main
gdb ./main
break main
run
next
print ptr
You will see ptr = 0x0 → null pointer → crash.
Best Practices
- Always compile with
-g - Disable optimization (
-O0) while debugging - Use meaningful variable names
- Reproduce bugs consistently
- Use watchpoints for tricky bugs
- Learn keyboard shortcuts
Conclusion
GDB is an essential tool for any C/C++ developer. Mastering it allows you to deeply understand program execution, memory behavior, and runtime issues. While it may feel complex initially, consistent practice will make debugging faster and more efficient.
If you are serious about systems programming, learning GDB is not optional—it is fundamental.
Top comments (0)