GDB, the GNU project debugger, is a powerful debugging tool for C, along with many other languages. It allows you to poke around inside your C programs while they're executing, and it also gives you the opportunity to see exactly what happens when your program crashes. It's pretty nifty, right? GDB is free software, and it runs on many popular unix and Windows-based operating systems. So it's a very widespread tool. You should learn to love it. GDB pros have a much easier time tracking down bugs than those who muddle through using guesses and infinite amounts of print-f statements. GDB is a command-line tool, which means you interact with it in a terminal, issuing commands via the keyboard instead of clicking buttons with your mouse. To start up GDB, you literally just type GDB at the prompt and hit Enter. You'll see some lines printed out to the screen showing you the version of GDB that you're running, and it's copyright information. And at the end, you'll see the GDB prompt, OpenParenthesis, GDB CloseParenthesis. This lets you know that GDB is ready for commands. At this point, the most important thing to know how to do is quit. Fortunately, this is pretty simple. The quit command does just that. As a shortcut, you can just use Q2. As fun as booting up GDB and promptly quitting is, let's now talk about using GDB to help debug a program. To start, I've got a program here in factorial.c that gets an int and attempts to compute its factorial. In case you haven't seen factorials before, don't remember them. The factorial of a number n is equal to the product of n, n minus 1, n minus 2, and so on until you hit 1. Therefore, the factorial of 3 is 3 times 2 times 1 or 6, and the factorial of 4 is 4 times 3 times 2 times 1 or 24. The factorial of 0 is an odd case. It's 1. And the factorials of negative integers aren't defined. Anyway, something about my factorial program is funky. When I run it, it prints out weird numbers that have nothing to do with factorials. So we can use GDB to help figure out what's going on. GDB operates on executable files, which are the binary files produced by the compilation process. That is, we can't run GDB on our .c or .h source code files like factorial.c. We want to run it on just factorial instead. If the program required any command line arguments, this is where we'd specify them. In this case, factorial doesn't require any command line arguments, so we just type run or r for short. This will start the factorial program running. When the program stops running, I'll get my GDB prompt back. Okay, let's try the same thing again, factorial of 4. All right, we see that we're getting the same kind of junk here in GDB. Now that the program has finished, we can't go in and access any of its state, so we'll need to start it running again before we can see what's happening. However, we need a way to stop it while it's in the middle of its run. To do that, we use what's called a break point. Breakpoints tell GDB to pause the program at a particular function or source code line so that we can examine the state of the program, the values of variables and the state of memory and such, at that point. Since I don't really know where things are going wrong, I just want to start debugging right at the very beginning, right when main begins. We'll set a break point at the beginning of main, using the break command. We can also use b to abbreviate break. Now let's start the program running again. Here we are at the beginning of main, just like GDB tells us. The line of code that's about to execute, but hasn't yet, is the printf line. We can tell GDB to execute this line of code and go to the next line with the next or n command. All right, now GDB tells us that we're on the get-int line. I know that it seems like the printf line didn't run since we don't see enter a positive integer printout on the screen, but it did actually run. What we're seeing is the operating system suppress writing anything to the screen until it absolutely has to, which is why debugging with printfs can sometimes seem unreliable. Anyway, let's again go to the next line of code and enter in an int. Again, let's type four. Hmm, so this looks weird. We're on line 12 according to GDB, but the next line that's about to execute is just a curly brace. That just means where the end of a loop are due while loop, in fact, and GDB is telling us that the termination condition, namely, none less than zero, will execute next. If this ever gets a little confusing, we can pull up the source code in GDB with the list or l command. This prints out the source code that's centered around the line that we're currently on. If we type list or l again, we'll see the next set of lines print out. We can do this until we hit the end of the file. To get back to where we were, we can supply list with a line number, in this case, line 12. Anyway, let's move on. Now we're on the for loop. Let's make sure that our num variable contains four. We do this with the print or p command. So GDB tells us that num is indeed storing four, as we expected. The dollar one that GDB prints out is a special GDB variable that is now set to store the number four as well. You can ignore this for now, but these GDB variables come in super handy in more advanced cases when you want to recall what you've done in the past. Anyway, moving on with next, we see that we start moving through the for loop. Let's keep going through here with n bit by bit. Rather than typing n each time, we can also just hit enter. When you hit enter without typing anything, GDB just repeats the previous command. So now we've hit the print def call. It looks like we've indeed gone through our for loop four times, which is what we want to do in order to multiply by one, two, three, and four. Everything seems like it's working, except when we hit next again, we get this huge number instead of 24. If we print out the value of factorial using p, we see that factorial does have this massive number in it. Something's definitely going wrong. At this point though, we are almost at the end of the program, and it's too late to fix anything. However, we can restart the program by typing r again and then y to confirm. Now we're back at our break point at the beginning of main. We know that everything seems to be fine with reading in the end, so we can jump ahead with n. Alternatively, we can set a new break point after the do while loop and jump there. Let's do that. Looks like line 14 comes just after the loop. Let's set a break point there. It's good practice to specify the file name in this break point command, since gdb can get confused if you're working with multiple files. To move ahead to this break point, we'll use the continue or c command. Okay, here we are at the for loop. Let's go one more line into the for loop, and then we'll start printing variables to see what's going on. Let's make sure that i is indeed one, as expected. Yep, that's all good. What about factorial though? Whoa, that's no good. We've got a big negative number here. How'd that happen? Well, if we look back at the code, we see that we never initialized it, so we've just got trash in there. That'll definitely throw off our calculation. Fortunately, we don't have to leave gdb to fix this. We can initialize it right here and fix it in the code later using the print command. We'll initialize it to one since the factorials of zero and one are both one. If we initialized it to zero, then we'd always end up with zero as our result. You can set any variable this way, which is super handy. Now let's continue our program. Let's make sure everything's where it's supposed to be. NUM should be four, i should be one, and factorial should be one two. We can shortcut this process and print all of our local variables with the super helpful command info locals, which prints out all of our in scope local variables. Anyway, it looks like everything's good to go. Let's do another go around of the loop just to make sure. Okay, everything looks great. Now we can use the continue command to go to the end. Sweet, four factorial printed out 24, as expected. Now we can go fix this in our code. Rather than quit out of gdb, we'll use another terminal tab to do this. Going back to our gdb tab, we now need to recompile our executable. One of the best things about gdb is that you don't need to leave gdb to run make. So that we don't keep hitting the old break points, let's disable them with you guessed it, disable command. This will disable all of our break points. Now we can restart the program with r and make sure everything's okay. Looks like everything's good to go. Factorial of four prints out 24, just like we thought. gdb is one of the most helpful tools you've got in your toolbox. There are a ton of more things you can do with gdb, far more than you can with simple print fs. Next time your program isn't doing what you'd like, try running gdb to figure out what's going on inside. With a little bit of practice, you'll be able to drill down right on your bug in no time. My name is Nate Harterson. This is CS50.