Debugging with GDB

A powerful command-line debugger for low-level languages

GDB is a debugger for a range of fairly low-level languages. It’s useful for finding issues in your code when it crashes or goes wrong. This guide will talk you through the basics of using GDB for debugging your software.

Launching GDB

To launch gdb you need to build your project first. A good build tool for low-level projects is meson if you’re not already using it check it out. Of course, you can use any build tool you like (including gcc directly).

To use GDB, run gdb with the program as an argument:

 ninja -C build/ # or whatever your build tool of choice is
 gdb ./build/myProg

If you didn’t set the program to debug when starting GDB, you can also do so once GDB has started using file:

 file ./build/myProg

Running your program

When GDB starts, your program will not automatically run. This can be useful for setting breakpoints or doing some setup before the program starts (eg, setting environment variables and the working directory or redirecting outputs).

You can use the run command to start execution:

run

Debugging

The simplest way to use GDB is simply to do the thing that causes the crash. GDB will intervine when this happens and you’ll get a chance to inspect the state of the program at the point of the crash. You can also add breakpoints to let you do the same thing without the program crashing.

The call stack

One of the most useful things to know when trying to debug programs is the place that the crash happened and how the program got there. To access this infomation you can use the backtrace (bt) command:

 # TODO show the backtrace
 bt

Variables

It can also be helpful to know the state of variables.

To get the current state of a variable, you can use p followed by the variable name:

 p foo

You can also use :: to access variables that are not currently in scope, but are defined (such as globals, or variables from parent objects that have local variables with the same name:

 p bar::foo-

Breakpoints

GDB isn’t only useful to help find the source of a crash. It also can be used to examine how the program got into a particular state (eg, to diagnose logic errors). You can ask the program to stop once a particular line is reached, allowing you to inspect the program’s state. The break command lets you do this:

 break 42 # break on line 42
 break foo.cpp:42 # break on line 42, in file foo.cpp
 break foo # break when function foo is called
about 500 Words.