Tips for Productive Debugging with GDB
In this post I’ll share my favorite tips for getting the most out of GDB.
Tip #1: Try GDB Dashboard
This may or may not be your cup of tea, but if, like me, you like having access to more program information at every break stop you may want to try GDB Dashboard.
It is a fantastic modular interface that comes as a .gdbinit
replacement and, with all modules enabled, looks like this:
Take a look at the Github repository for the project for more information on how to customize it to fit your needs.
Tip #2: Use a global .gdbinit
and a project .gdbinit
.gdbinit
is the configuration file that gdb sources at startup. You can have one in your home directory (~/.gdbinit
) for global settings, and one in the current directory (./.gdbinit
) for project specific settings.
As you will see from the following tips, project specific settings for gdb can be useful for custom formatters or aliases.
Note: you must enable project specific .gdbinit
files with the set auto-load local-gdbinit
.
Tip #3: Use custom formatters
Custom C/C++ types can be noisy to inspect in the debugger, especially if implemented using unions
.
With gdb’s Pretty Printing you can define custom formatters for your data types in order to make them more readable.
For example, in Rival Fortress I have a matrix data type (MPEMatrix4
) that is a union
of many anonymous structs for developer convenience. This is what it looks like before and after using a custom print formatter:
And this is the source for the custom formatter:
It assumes that the matrix type has a flat[16]
member field.
Tip #4: Use aliases
Aliases are an excellent way to speed up your day to day debugging. You specify them in your .gdbinit
and look like this:
alias -a w = dashboard expression watch
Tip #5: Use automatic $
variables
Whenever you inspect something using the print
command, gdb automatically stores the result in a variable like so:
The $1
is the automatic variable, and you can reference it later like so:
Tip #6: Inspect array pointers
When working with plain C-style pointer to an array you can use the following command:
>>> print *Array@10
This will print 10 items from the Array
pointer.
Tip #7: Enable command history
Enable command history by adding the following to your .gdbinit
:
set history save on
By default the history file (.gdb_history
) is saved in the current directory, but if you want you can share histories by explicitly setting the output filename with set history filename <fname>
.
Tip #8: Detect if the debugger is running
This is not really a gdb specific tip, but it is useful nonetheless.
On Windows you can use the IsDebuggerPresent function to detect if a debugger is running. You can do the same on Unix-like systems using the following function: