Debugging Native Programs with gdb
Compile programs with debug information to enable meaningful inspection with gdb.
gcc -g -O0 -o myprog myprog.cExplanation:
-gembeds debugging symbols (function names, line numbers, local variable types).-O0disables optimizations that can move or remove variables; for interactive debugging this simplifies reasoning about state.
Start a session and basic workflow
Section titled “Start a session and basic workflow”Start gdb with arguments:
gdb --args ./myprog arg1 arg2Inside gdb, a minimal session looks like:
break main— set a breakpoint atmain.run— start the program.- When stopped:
btto inspect the call stack,frame 2to switch frames,print varto evaluate expressions. nextsteps over function calls;stepsteps into them.
Common commands summary:
run— start programbreak <function|file:line>— set breakpointdelete— remove breakpointsinfo breakpoints— list breakpointsnext/step— step over / intocontinue— resume executionbt/backtrace— show call stackframe <n>— select stack frameprint <expression>— print variable or evaluate expressionset variable x=42— change program state
Example: diagnose a segmentation fault
Section titled “Example: diagnose a segmentation fault”Given a crash, run the program under gdb or load a core file:
ulimit -c unlimited./myprog# if it crashes and produces coregdb ./myprog core# or run under gdbgdb --args ./myprogrunUse bt to see where the crash occurred. Example output:
#0 0x00007ffff7a3341a in strcpy () from /lib/x86_64-linux-gnu/libc.so.6#1 0x4006f4 in unsafe_copy (src=0x602010 "...", dest=0x7fffffffe2c0 "...") at buffer.c:12#2 0x400710 in main () at hello.c:24frame 1 then print src and print dest will show values in that frame. Use list to show source lines around the crash.
Conditional breakpoints, watchpoints, and signals
Section titled “Conditional breakpoints, watchpoints, and signals”- Conditional breakpoint:
break foo if x==0— stops only when condition true. - Watchpoint:
watch myvar— stops whenmyvarchanges (hardware watchpoints are limited by CPU support). - Catch signals:
handle SIGSEGV print passconfigures how gdb reports and delivers signals.
Inspecting complex data and C++ containers
Section titled “Inspecting complex data and C++ containers”For C++ STL containers, enable pretty-printers (usually shipped with libstdc++ debug helpers). If not enabled, install python3-libstdc++-v6 or configure gdb’s python pretty-printers. Then print std::vector_var shows contents nicely.
Remote debugging with gdbserver
Section titled “Remote debugging with gdbserver”To debug on a target machine (or VM/container), run gdbserver on the target and connect from the host:
On target:
gdbserver :1234 ./myprog arg1On host:
gdb ./myprogtarget remote target-ip:1234continueThis lets you use the host’s gdb and source while the program runs on the remote device.
Automating and CI-friendly backtraces
Section titled “Automating and CI-friendly backtraces”In CI or automated test environments capture a backtrace non-interactively:
gdb --batch -ex 'run' -ex 'bt full' --args ./myprogOr when you have a core file:
gdb --batch -ex 'bt full' ./myprog core > core-backtrace.txtUseful integrations and tips
Section titled “Useful integrations and tips”addr2line -e ./myprog 0x4006f4converts addresses to file:line when you only have an address.- Use
set print pretty onandset pagination offfor cleaner output in scripts. - For Python extensions or GDB Python scripting, use
pythonblocks inside gdb to automate tasks.
Advanced: perf and combined workflows
Section titled “Advanced: perf and combined workflows”When a bug is intermittent or performance-related, combine perf record/perf report to find hotspots, then reproduce the problematic region under gdb to inspect state.
Troubleshooting gdb itself
Section titled “Troubleshooting gdb itself”If gdb reports missing symbols, ensure you built with -g and did not strip the binary. Use file and readelf -S ./myprog to inspect symbol sections.
- Build with
-g -O0for interactive debugging; use-g -O2for release with some symbol info retained. - Use
gdb --batch -ex 'run' -ex 'bt' --args ./myprogin CI to capture backtraces for failing tests. - Save core dumps with
ulimit -c unlimitedwhen reproducing crashes locally.