Debugging C++ with GDB
Authors: Tiago P. Peixoto1, Lena Mangold1
Affiliations: 1Inverse Complexity Lab
License: CC-BY
GDB stands for GNU Debugger, and it provides a more robust debugging infrastructure than using print statements in your code.
A simple introduction to using GDB can be read here. Please take a look there.
To debug some C++ code that is called from python, you should call gdb with the python interpreter:
$ gdb `which python`
GNU gdb (GDB) 16.3
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /sbin/python...
Downloading separate debug info for /usr/bin/python3.13
Reading symbols from /home/count0/.cache/debuginfod_client/76195980c4ccf58a63406c313d47a475eabc0bbe/debuginfo...
(gdb)
You can then load your script my_script.py
with:
(gdb) set args ./my_script.py
(gdb) run
Recompile with debug symbols¶
GDB works best when debug symbols are included during compilation. This can be done using the -g
flag during compilation.
It is also possible to include a DEBUG flag in the Makefile, as is shown in the following example. Compiling in debug mode will then include debug symbols (-g
), disable optimisation (-00
), and enable assert()
by omitting -DNDEBUG
.
CXX=g++
DEBUG ?= 0
ifeq ($(DEBUG), 1)
CXXFLAGS=-g -O0 -fopenmp -std=gnu++17 -Wall -fPIC -DPIC `pkg-config --cflags graph-tool-py` -DBOOST_ALLOW_DEPRECATED_HEADERS
else
CXXFLAGS=-O3 -fopenmp -std=gnu++17 -Wall -fPIC -DPIC `pkg-config --cflags graph-tool-py` -DBOOST_ALLOW_DEPRECATED_HEADERS -DNDEBUG
endif
LDFLAGS=`pkg-config --libs graph-tool-py` -shared
SOURCES=$(shell echo *.cc)
HEADERS=$(shell echo *.hh)
OBJECTS=$(SOURCES:.cc=.o)
TARGET=libexample.so
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(TARGET)
$(OBJECTS): %.o: %.cc %.hh example.hh
$(CXX) $(CXXFLAGS) -c $< -o $@
$(TARGET): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LDFLAGS)
To recompile in debug mode, run
make clean
make DEBUG=1
Useful GDB commands¶
Command | Description |
---|---|
run (r ) | Run the program until it finishes, crashes, or hits a breakpoint |
start | Run and pause at the first line of main() |
next (n ) | Execute the next line (step over function calls) |
step (s ) | Execute the next line (step into function calls) |
continue (c ) | Resume execution until the next breakpoint or crash |
break file.hh:N or b file.hh:N | Set a breakpoint at line N in file.hh |
break func | Set a breakpoint at function func() |
delete | Remove all breakpoints |
print var or p var | Print the value of variable var |
list (l ) | Show source code around current line |
info locals | Show all local variables |
quit (q ) | Exit GDB |
Workflow Example (for C++ code called from Python)¶
If the Makefile includes the DEBUG
flag and the make clean
command as in the example Makefile above, the following is an example workflow for debugging C++ code that is called from Python.
make clean # Delete compiled .o files and output .so files
make DEBUG=1 # Compile with debug flag
gdb `which python` # Start GDB
(gdb) set args ./my_script.py # Load your script
(gdb) break headerfile.hh:N # Set a breakpoint in line N in headerfile.hh
(gdb) run # Run and pause at breakpoint
(gdb) info locals # Show local variables
(gdb) next # Step over some line
(gdb) print alpha # Check value of variable alpha
(gdb) continue # Resume until crash or breakpoint
(gdb) quit # Exit