We’re going to use gdb from the terminal to debug programs in this course.
Many software development environments integrate with debuggers, but these user interfaces often present the same functionality you’ll see in gdb on the terminal.
The interfaces vary quite a bit, but gdb is available just about anywhere so it’s a good place to start learning to use a debugger.
There was a lot of information in our reading, but you may want to refer back to the Quick Reference section as you work through this lab.
To get started, download the gdb.tar.gz file and run the following commands to extract today’s starter code:
$ cd csc161/labs
$ tar xvzf ~/Downloads/gdb.tar.gz
$ cd gdb
We’ll start using gdb to try to decipher an interesting (but broken) C program that uses recursive functions.
The following exercises refer to the code in partA.c.
Driver: student closer to the whiteboard
Read through the partA.c program.
Discuss the code with your partner and move on once you understand as much as you can without running it.
Compile the program with the command make partA and run it on a few inputs.
Move on once you’ve found at least one input where the program produces the right answer and one where it produces an incorrect answer.
Write down these two inputs, the expected outputs, and what the program produces.
Run gdb ./partA to start gdb, and then set two breakpoints: one on line 51 (which evaluates addition) and a second on line 53 (which evaluates subtraction).
Refer to the gdb quick reference or today’s reading if you’ve forgotten how to do that.
Now run the program with the run command in gdb, and enter the input 5-10+3+1+18.
The debugger will stop the program each time it evaluates addition or subtraction.
You can use the print command to show the values of a given variable in the program at the point where it is stopped.
You can also use the backtrace command to see where the chain of function calls that led to this point in the program.
Once you’re done looking around, use the continue command to resume execution until the next breakpoint.
If you want to start the program again just enter the run command.
Use these tools to follow the way the program evaluates the expression until you can explain why the program gives an incorrect answer.
This part of the lab focuses on partB.c, a (broken) implementation of the Sieve of Eratosthenes.
Driver: Student farther from the whiteboard
Review the code in partB.c to try to understand how this program is supposed to find primes.
You’re also welcome to review the Wikipedia page about this algorithm if you’re unsure what the code is trying to do.
Compile the program with make partB and run ./partB to see what the program actually does.
It should be fairly obvious that there is something wrong with this implementation: it never finds any primes.
We’re going to use watchpoints to figure out why the program doesn’t find any primes.
Launch gdb with the command gdb ./partB.
Instead of running the program, we’re going to use the start command to start its execution but stop when we get to the top of main.
Choose your favorite prime number between 0 and 100 (make sure it’s actually prime).
Now, we’re going to set a watchpoint to see when that number, which should always be considered prime, changes state in the is_prime array.
Run the command watch is_prime[P] where P is your chosen prime number.
Type continue to resume the program.
The program should stop almost immediately, where it will show you that the value of is_prime[P] is changing.
Find this point in the code, look at the values that change, and decide whether this is the source of the error or not.
You’re also welcome to use print to look at the values of variables where the program stopped.
If you don’t think you’ve found the error yet, type continue again and look at the next change.
Use watchpoints and the tools you learned in the previous part of this lab to figure out why the program isn’t finding any prime numbers.
You may need to run the program several times to pinpoint the error.
Write down your explanation and move on.
Use your discovery from the previous step to fix partB.c so it correctly finds prime numbers.