5.5. GDB#

gdb is your best friend when it comes to debugging. It allows you to step through a program line by line, examine variable values and the contents of the stack, and much more. For a quick reference, we recommend this guide.

5.5.1. Getting started#

In order to use gdb, you will have to use the -g command line flag when compiling. This flag makes sure that the necessary debugging information is produced.

gcc -g -o main main.c

This will compile the program main.c into an executable named “main” with debugging information.

To open the program in the debugger, you can type gdb main. To exit gdb, type q or quit.

Gdb provides documentation, which you can access by typing the command help. This will provide a list of topics, and you can then get information about a specific topic or command by typing help <topic> or help <command>.

5.5.2. Using gdb to debug#

One of the more useful things you can do in gdb is set breakpoints and observe the state of the process mid-execution. There are a couple of ways to set a breakpoint:

  • break <function>: sets a breakpoint at the beginning of function.

  • break <linenumber>: sets the breakpoint to the given line number in the source file. Execution will stop before that line has been executed.

If your code is in multiple files, you may have to specify a file name before the function name or line number, e.g. break <filename>:<function> or break <filename>:<linenumber>.

To delete the breakpoints you have set, you can type delete. You can also delete a specific breakpoint by typing delete <number>. To find out what number each breakpoint is, type info breakpoints.

Once you have set all your desired breakpoints, you need to run the program. To do this, simply type the command run into gdb. If the program takes command line arguments, you can provide them the same way as you would in the command line, except you say “run” instead of the program name. Your code will execute up to where you specified your first breakpoint.

Once you reach your breakpoint, you will probably want to look at the contents of the stack or some variables to make sure that your program is executing as expected. To see the current value of a variable, you can simply type print <variablename>.

To continue running the program after stopping at a break time, you have several options. Typing continue will set the program running again until you hit another breakpoint or the process finishes. Typing step (or just s) will execute the current source line and stop execution before the next source line, If the line that is about to be executed is a function call, then step will step into that function. In contrast, moving through execution using the next will not “step in” to a called function. It will continue until the next source line in the current function.

5.5.2.1. Debugging threads#

Once you learn about pthreads, a very powerful thing you can do is switch between threads and step through in the order you choose.

  • info threads: lists all existing threads.

  • thread <thread_id>: selects which thread to switch to.

After you have selected which thread you would like to step through, you can use the basic stepping commands to execute the next instructions. Note that already existing break points exist across all threads.

5.5.2.2. Debugging signals#

Once you learn about signals, you can use gdb to change its behavior on how to handle those signals.

  • info signals or info signals <signal>: lists all signals (or one signal) and shows how gdb responds to it.

  • handle <signal> <keyword>: changes how gdb responds to that signal based on the keyword.

Below is a list of keywords:

  • nostop: gdb should not stop your program when this signal happens.

  • stop: gdb should stop your program when this signal happens.

  • print: gdb should print a message when this signal happens.

  • noprint: gdb should not mention the occurrence of the signal at all.

  • ignore: gdb should not allow your program to see this signal.

  • noignore: gdb should allow your program to see this signal.

5.5.3. Review#

  • break: use to set breakpoints

  • run: run the program in gdb

  • delete: delete breakpoints

  • continue: set the program running again after being stopped at a breakpoint

  • step: execute the current source line and stop again before the next source line

  • next: continue until the next source line in the current function

  • list <linenumber>: print out some lines from the source code around linenumber.

This is just the beginning of what you can do with gdb, and we will add to this section of the book as the course continues!