"Debugging" refers to the process of finding and fixing errors, or "bugs" in a program. The term comes from Admiral Grace Hopper who, while working on an early computer in the 1940s found a moth stuck in the computer. Now bugs are rarely caused by actual insects, but by errors in our code.
A "debugger" is a program that assists us in the task of debugging. Today we will look at two debuggers for C++, gdb and ddd.
A debugger works by reading extra information in your program. This extra information, also called "debug symbols" is not put into our programs by default. In order to make clang++ add this in, we must compile our code with the "-g" option:
Now the executable "file" is ready to be debugged!
$ clang++ -g file.cpp -o file
Then you can give gdb various commands to run and investigate your program:
gdb commands also support tab-completion which is handy when setting breakpoints. With gdb you can step through your program and display values while the program runs.
When a program crashes, gdb is especially useful. Run the program through the debugger, and it will stop just before crashing so you can see what line of code caused the problem, what values were in any variables, and so on. You can try debugging the segfaults in this example.
Because gdb is somewhat awkward to use, several front-ends have been developed for it. A front-end is a program that provides a nicer interface to another program.
ddd is a GUI program, so it can only be run on the actual lab machines*. We start ddd the same way as gdb:
$ ddd file
Using ddd is just like gdb, except it also provides a GUI to use the features.
*it is actually possible to run GUI programs remotely, but is hard to setup, and really slow.
To practice using the debugger, debug this program. This code produces a segfault if the user enters a non-negative input.
Copyright © 2018 Ian Finlayson | Licensed under a Creative Commons Attribution 4.0 International License.