The GNU debugger (Gdb)

This guide will introduce you about how to debug your c programs with gdb.

Lets start with its invocation, if your program is just an executable without arguments you just have to run:

$ gdb ./program

Or if your program needs arguments to run add the option --args to gdb use:

$ gdb --args ./program arg1 arg2 ...

Now you are on the gdb terminal, maybe you feel lost and you don’t know which commands are available in this new terminal, so let me show you the important ones (or at least the ones that I use most).

Displaying the code of the program

To check the code use:

(gdb) list
(gdb) l

Or if you wish to avoid having to run these commands constantly to see the code use the command:

(gdb) layout src

It will convert your boring terminal into a window showing the code you need to check and a terminal behind to put more gdb commands, one of the trade-offs of this mode is that your arrow keys will be used to navigate into the code blocking the ability on your terminal to move the cursor, backward and forward, to return to the previous mode execute:

tui disable

Telling Gdb where to pause the program

Before running the code we need to specify where the program should stop, after all we are debugging code. The command to do that is break and you can use it in multiple ways:

(gdb) break LINENUMBER
(gdb) break FUNCTION_NAME
(gdb) break FILE.c:LINENUMBER
(gdb) break FILE.c:FILE_FUNCTION_NAME
(gdb) b LINENUMBER
(gdb) b FUNCTION_NAME
(gdb) b FILE.c:LINENUMBER
(gdb) b FILE.c:FILE_FUNCTION_NAME

Suspicious readers have noted that list and break command have a shortened versions which begin by just its first character so to avoid redundancy the next commands that have their shortened versions will be written in the following way:

c[ommand]

Here is one example with break and list:

(gdb) b[reak] LINENUMBER
(gdb) l[ist]

Running the code

Now we know how to stop the program, lets start it, to run the program for the first time use the command:

(gdb) r[un]

If a breakpoint was set before, the program will stop there. Once the program stops you can use list to check where you are. If you need to advance one line at a time in the program put:

(gdb) n[ext]

Also there is a similar command that will get into subroutines when possible, for example if you stop on a function and you want to dive in the function to check if everything is fine is better to use:

(gdb) s[tep]

If Instead of advancing one line at time you need to go until a specific line the command:

(gdb) u[ntil] LINENUMBER

will be helpful, another command useful to execute the program until the next breakpoint is:

(gdb) c[ontinue]

And if for whatever reason you need to restart the program use again the command:

(gdb) r[un]

Looking variables

Now you stopped where you wanted, its time to check if the variables at that state of the program have its expected values. The first we will is:

(gdb) p[rint] VAR_NAME

with print, you can check not only single variables, it you want you can see arrays or structs variables, it is even possible to the value of pointers using the following syntax:

(gdb) p[rint] *PTR@NUMBER_OF_FIELDS

The other one I use often is:

(gdb) printf "FMT_STR", VAR1, ...

it works in the same way as a C printf function and is usefull to show multiple variables at one call, where is one example showing a string and an integer

(gdb) printf "%d: %s", INTEGER_VAR, CHAR_PTR_VAR

Closing GDB

Now you finally found the bug, and you know how to fix it, but to your surprise you don’t know how to exit gdb, well the command is easy:

(gdb) q[uit]

And Finally getting help

With the commands explained above you have a basic understanding of how to debug with gdb but this is just a taste, sometimes you need more information, to get it you can use:

(gdb) h[elp]
(gdb) h[elp] COMMAND
(gdb] h[elp] TOPIC

help command will show you the available commands on gdb and how to use them, the rest is up to you.