00:00:00,500 --> 00:00:03,150 DOUG LLOYD: So if you're anything like me, when you write code 00:00:03,150 --> 00:00:06,240 it's not always going to be perfect. 00:00:06,240 --> 00:00:08,820 There's usually going to be something wrong with it. 00:00:08,820 --> 00:00:11,550 And that is known as writing bugs. 00:00:11,550 --> 00:00:13,680 And part of being a computer programmer is 00:00:13,680 --> 00:00:16,604 learning how to debug, or remove the bugs, from programs. 00:00:16,604 --> 00:00:19,020 And there are a lot of different techniques and strategies 00:00:19,020 --> 00:00:20,620 that one might use to do this. 00:00:20,620 --> 00:00:22,578 And what I want to do in this video is show you 00:00:22,578 --> 00:00:25,590 three of the tools that are baked into CS50 IDE 00:00:25,590 --> 00:00:28,680 that you can use to help with your debugging, 00:00:28,680 --> 00:00:31,639 or help trying to figure out what's going on in your system. 00:00:31,639 --> 00:00:34,680 And these three tools, which I'm going to just display the names of here, 00:00:34,680 --> 00:00:39,490 are known as debug50, eprintf, and help50. 00:00:39,490 --> 00:00:42,150 We're actually going to cover those in reverse order. 00:00:42,150 --> 00:00:43,650 So we're going to start with help50. 00:00:43,650 --> 00:00:45,858 So I have a couple of files pre-configured in my IDE. 00:00:45,858 --> 00:00:49,710 I'm going to navigate into my help50 directory. 00:00:49,710 --> 00:00:52,470 And just clear the terminal window here. 00:00:52,470 --> 00:00:54,750 And what help50 basically does, it is designed 00:00:54,750 --> 00:00:58,150 to be sort of a virtual teaching fellow of sorts. 00:00:58,150 --> 00:01:01,890 It basically is trying to give you clues and hints about what might be going on 00:01:01,890 --> 00:01:05,430 in your program or when you're trying to work with your program 00:01:05,430 --> 00:01:08,310 and something goes wrong without just giving you the answer outright. 00:01:08,310 --> 00:01:11,185 So it's trying to nudge you along in the right direction in the hopes 00:01:11,185 --> 00:01:14,130 that it's an issue that, with a little bit of encountering and having 00:01:14,130 --> 00:01:16,713 the computers sort of give you a little bit of back and forth, 00:01:16,713 --> 00:01:20,520 it's an issue that you'll learn to be able to not recreate in the future. 00:01:20,520 --> 00:01:23,010 So I have a couple of example programs here. 00:01:23,010 --> 00:01:27,170 All of them are written in C. And let's just try and compile the first one. 00:01:27,170 --> 00:01:31,300 So let's try and make example one. 00:01:31,300 --> 00:01:31,977 Error. 00:01:31,977 --> 00:01:34,060 So this is where help50 is going to come in handy. 00:01:34,060 --> 00:01:37,000 Generally it's going to be used when you're working. 00:01:37,000 --> 00:01:40,360 It's not so much a bug in your program that is 00:01:40,360 --> 00:01:42,430 during runtime, a runtime error. 00:01:42,430 --> 00:01:45,580 This is going to be a logical bug, or some kind 00:01:45,580 --> 00:01:48,950 of bug that prevents your program from being compiled 00:01:48,950 --> 00:01:52,240 is going to be the most common use case of help50. 00:01:52,240 --> 00:01:55,750 So here I'm getting told I'm implicitly declaring library function 00:01:55,750 --> 00:01:57,214 printf with blah, blah, blah. 00:01:57,214 --> 00:01:58,630 There's a whole lot of text there. 00:01:58,630 --> 00:02:02,479 Now, what help50 tries to do is it looks at that error message for you. 00:02:02,479 --> 00:02:04,270 And if there are multiple ones it will look 00:02:04,270 --> 00:02:05,800 at the first error message for you. 00:02:05,800 --> 00:02:08,979 And it will try and translate that kind of arcane language 00:02:08,979 --> 00:02:12,144 into something a little more, hopefully, intuitive to use. 00:02:12,144 --> 00:02:14,310 And the way we use help50 is pretty straightforward. 00:02:14,310 --> 00:02:20,950 We first type help50, and then we do exactly the command we tried to do. 00:02:20,950 --> 00:02:23,320 So in this case it's help50, make example1. 00:02:23,320 --> 00:02:26,470 Let's see if maybe help50 can give me a little more information about what 00:02:26,470 --> 00:02:29,800 I might be doing wrong in my program. 00:02:29,800 --> 00:02:30,930 So I run it again. 00:02:30,930 --> 00:02:34,020 Now, I'm getting this sort of hint from the virtual TF, 00:02:34,020 --> 00:02:35,790 which is written here in yellow. 00:02:35,790 --> 00:02:38,790 "Did you forget to #include stdio.h in which printf 00:02:38,790 --> 00:02:40,400 is declared atop your file?" 00:02:40,400 --> 00:02:41,400 Well, let's take a look. 00:02:41,400 --> 00:02:45,760 So in example 1.c, it looks like I did kind of forget to do that. 00:02:45,760 --> 00:02:51,310 So if I just go ahead and add that, and I save, 00:02:51,310 --> 00:02:55,580 and I try and make example one again maybe. 00:02:55,580 --> 00:02:56,850 Hey, it compiled. 00:02:56,850 --> 00:02:57,690 It worked just fine. 00:02:57,690 --> 00:03:00,975 So I can now run the example1 program, hello world. 00:03:00,975 --> 00:03:04,100 Now, of course, I have a logical bug here where I didn't put a backslash n. 00:03:04,100 --> 00:03:06,067 So it kind of ran into a new line like that. 00:03:06,067 --> 00:03:06,650 But that's OK. 00:03:06,650 --> 00:03:09,390 That's something I can go ahead and fix pretty easily. 00:03:09,390 --> 00:03:11,744 So let's try and compile example two. 00:03:11,744 --> 00:03:14,660 And we'll go through this again where we won't look at the source code 00:03:14,660 --> 00:03:15,400 beforehand. 00:03:15,400 --> 00:03:18,350 We'll just try and compile it, thinking we're pretty close, 00:03:18,350 --> 00:03:19,290 and see what happens. 00:03:19,290 --> 00:03:23,310 So we'll try and make example2. 00:03:23,310 --> 00:03:23,810 Oh. 00:03:23,810 --> 00:03:25,340 Seven errors generated. 00:03:25,340 --> 00:03:26,331 That's not good. 00:03:26,331 --> 00:03:27,830 But, again, help50 can help us here. 00:03:27,830 --> 00:03:29,538 And what it's going to do in this case is 00:03:29,538 --> 00:03:33,090 it's going to look at the very first one and give us a hint for that one. 00:03:33,090 --> 00:03:35,689 Now, oftentimes when you get a lot of errors from compiling 00:03:35,689 --> 00:03:37,980 it's not necessarily that I've done seven things wrong. 00:03:37,980 --> 00:03:39,729 In fact, if you look at the program you'll 00:03:39,729 --> 00:03:42,320 see that it's not that many lines of code when we do. 00:03:42,320 --> 00:03:45,200 But really it's just one error that sort of cascades and creates 00:03:45,200 --> 00:03:47,990 another one because it doesn't understand what's happening before. 00:03:47,990 --> 00:03:50,150 And if you can fix that one error at the beginning, 00:03:50,150 --> 00:03:55,065 it might resolve one or more, or all, of the remaining errors. 00:03:55,065 --> 00:03:56,440 So I'll clear my terminal window. 00:03:56,440 --> 00:03:57,560 And we'll try this again. 00:03:57,560 --> 00:03:59,800 But we'll preface this by saying help50 first. 00:03:59,800 --> 00:04:03,370 So help50 make example2. 00:04:03,370 --> 00:04:04,780 Let's see. 00:04:04,780 --> 00:04:06,910 Use of undeclared identifier string. 00:04:06,910 --> 00:04:08,500 Did you mean standard in? 00:04:08,500 --> 00:04:09,890 Well, I'm assuming probably not. 00:04:09,890 --> 00:04:12,100 Let's take a look at my code. 00:04:12,100 --> 00:04:12,600 No. 00:04:12,600 --> 00:04:15,540 I meant to use string there on line five. 00:04:15,540 --> 00:04:18,630 So by undeclared identifier, Clang means you've used a name string 00:04:18,630 --> 00:04:20,850 on line five which hasn't been defined. 00:04:20,850 --> 00:04:25,269 Did you forget to #include cs50.h in which string is defined atop your file? 00:04:25,269 --> 00:04:26,310 Well, here, again, I did. 00:04:26,310 --> 00:04:29,620 I did forget to include cs50.h this time. 00:04:29,620 --> 00:04:31,590 So it gave me another clue here. 00:04:31,590 --> 00:04:33,300 But I had seven errors. 00:04:33,300 --> 00:04:34,970 So hopefully this resolves most of them. 00:04:34,970 --> 00:04:36,450 Lets clear this and see if it does. 00:04:36,450 --> 00:04:39,011 We'll try and make example2 again. 00:04:39,011 --> 00:04:39,510 And it did. 00:04:39,510 --> 00:04:42,450 So even though it said I had seven errors, I really didn't. 00:04:42,450 --> 00:04:44,100 I just had the one. 00:04:44,100 --> 00:04:46,980 And because that one kind of threw everything else off, 00:04:46,980 --> 00:04:51,120 it just kind of cascaded down and really messed us up. 00:04:51,120 --> 00:04:51,782 All right. 00:04:51,782 --> 00:04:53,240 Let's take a look at example three. 00:04:53,240 --> 00:04:55,830 We'll try and make example three. 00:04:55,830 --> 00:04:56,940 Seven errors again. 00:04:56,940 --> 00:04:57,830 Ugh, man. 00:04:57,830 --> 00:05:00,720 Let's see what I got here. 00:05:00,720 --> 00:05:04,460 Looks like I have a for loop that's going from 1 to 10. 00:05:04,460 --> 00:05:07,800 And it's supposed to print out a new integer on each line. 00:05:07,800 --> 00:05:10,410 That looks OK to me, at least at first glance. 00:05:10,410 --> 00:05:12,554 I don't really know what the issue could be here. 00:05:12,554 --> 00:05:14,470 But help50 might be able to help us out again. 00:05:14,470 --> 00:05:16,860 So we'll try one more time help50 make example3. 00:05:16,860 --> 00:05:19,380 And, again, you'll see that help50 is commonly 00:05:19,380 --> 00:05:22,310 going to be used most of the time-- although it's not all it can do. 00:05:22,310 --> 00:05:24,920 And we'll take a look at a couple of examples of that in a second. 00:05:24,920 --> 00:05:27,330 You're going to use help50 most of the time when there are compile time 00:05:27,330 --> 00:05:29,496 errors that prevent your program from being compiled 00:05:29,496 --> 00:05:31,240 and have to be resolved first. 00:05:31,240 --> 00:05:33,234 So we'll try and help50 this one. 00:05:33,234 --> 00:05:35,400 Looks like it says on line five it looks like you're 00:05:35,400 --> 00:05:38,910 trying to declare a variable that's already been declared elsewhere. 00:05:38,910 --> 00:05:40,000 I don't see that. 00:05:40,000 --> 00:05:41,220 But then it tells me a little bit more. 00:05:41,220 --> 00:05:44,095 If you meant to create a for loop be sure that each part is separated 00:05:44,095 --> 00:05:46,080 with a semicolon rather than a comma. 00:05:46,080 --> 00:05:50,040 So here I've got commas, and I'm supposed to have semicolons. 00:05:50,040 --> 00:05:53,640 So it's, again, little things like this where it's little syntax things where 00:05:53,640 --> 00:05:55,757 if you were able to get in touch with somebody 00:05:55,757 --> 00:05:58,590 you could just kind of look at your code really quickly and be like, 00:05:58,590 --> 00:06:01,710 oh, well, you really just need to put in a semicolon here instead of a comma. 00:06:01,710 --> 00:06:05,043 That's the kind of thing where it stinks to get stuck in a jam where you're just 00:06:05,043 --> 00:06:08,940 waiting for somebody to give you that sort of shining moment right 00:06:08,940 --> 00:06:11,610 where suddenly the error is revealed. 00:06:11,610 --> 00:06:14,580 You can use help50 to try and help you along and accelerate this 00:06:14,580 --> 00:06:17,580 so that you don't get stuck waiting, and you can get a little resolution 00:06:17,580 --> 00:06:20,262 for your errors a little more quickly. 00:06:20,262 --> 00:06:22,720 Of course, we'll just confirm with trying to make it again. 00:06:22,720 --> 00:06:24,060 And it compiled no problem. 00:06:24,060 --> 00:06:25,572 I could run this program. 00:06:25,572 --> 00:06:28,530 And it will print out the numbers 1 through 10, each on separate lines. 00:06:28,530 --> 00:06:31,488 We can't see them all here because my terminal window is not big enough 00:06:31,488 --> 00:06:33,760 to hold them, but they're all there. 00:06:33,760 --> 00:06:34,260 All right. 00:06:34,260 --> 00:06:35,700 I got one more example here. 00:06:35,700 --> 00:06:40,890 And then I'll show you two examples of using help50 not in the make context 00:06:40,890 --> 00:06:46,400 necessarily, or in the Clang context. 00:06:46,400 --> 00:06:50,530 So let's try and make example4. 00:06:50,530 --> 00:06:51,400 I have one error. 00:06:51,400 --> 00:06:54,450 "Expression result unused, n times 5." 00:06:54,450 --> 00:06:56,270 Not really sure what that means. 00:06:56,270 --> 00:06:58,949 So let's just quickly pop open example4 here at the top. 00:06:58,949 --> 00:07:01,240 Looks like what I want to do is have this print out 50. 00:07:01,240 --> 00:07:02,323 So I set n as equal to 10. 00:07:02,323 --> 00:07:03,970 I multiply n by 5 to get 50. 00:07:03,970 --> 00:07:06,160 And I want to print out 50. 00:07:06,160 --> 00:07:07,870 So I wonder what the issue could be. 00:07:07,870 --> 00:07:11,644 So let's help50 make example4. 00:07:11,644 --> 00:07:15,650 On line six of example 4.c you are performing an operation, 00:07:15,650 --> 00:07:18,350 but not saving the result. Did you mean to print or store 00:07:18,350 --> 00:07:19,460 the result in a variable? 00:07:19,460 --> 00:07:22,155 So remember, when we are doing mathematical manipulations 00:07:22,155 --> 00:07:24,780 to variables, we always have to assign the result to something. 00:07:24,780 --> 00:07:29,000 And here what I probably meant to say is either n equals n times 5, 00:07:29,000 --> 00:07:33,050 to change n from 10 into 50, or the more shorthand version, 00:07:33,050 --> 00:07:36,870 n times equals 5, which would also work just fine. 00:07:36,870 --> 00:07:37,900 So I can save this. 00:07:37,900 --> 00:07:38,900 Hopefully this fixes it. 00:07:38,900 --> 00:07:41,380 I'll try and recompile it. 00:07:41,380 --> 00:07:45,500 And I'll try and run it to see if I get 50 printed out. 00:07:45,500 --> 00:07:47,420 So that's a couple of uses of, in particular 00:07:47,420 --> 00:07:49,160 this is help50 helping with Clang. 00:07:49,160 --> 00:07:52,250 Although every time we were doing this we were typing make. 00:07:52,250 --> 00:07:55,570 Remember that make is actually just a wrapper 00:07:55,570 --> 00:07:58,220 for Clang, which is the name of the actual compiler 00:07:58,220 --> 00:08:00,262 that we're using in CS50 IDE. 00:08:00,262 --> 00:08:01,970 What happens though if I try and do this? 00:08:01,970 --> 00:08:04,310 There's no file called example5. 00:08:04,310 --> 00:08:06,191 So make example5. 00:08:06,191 --> 00:08:07,940 Unlike the previous four, this is actually 00:08:07,940 --> 00:08:09,950 going to be a help50 that helps with a message 00:08:09,950 --> 00:08:13,351 from make as opposed to a message from Clang. 00:08:13,351 --> 00:08:14,600 Now, obviously it's not there. 00:08:14,600 --> 00:08:16,475 So you can probably figure out what it means. 00:08:16,475 --> 00:08:19,990 But in case you didn't, I could preface it with help50. 00:08:19,990 --> 00:08:24,060 "Do you actually have a file called example5.c in the current directory?" 00:08:24,060 --> 00:08:25,310 Well, I don't. 00:08:25,310 --> 00:08:28,350 So I'm trying to compile a program that doesn't exist. 00:08:28,350 --> 00:08:30,530 So this is just help50, again, giving me a clue, 00:08:30,530 --> 00:08:33,179 like, well, maybe you're making a little bit of a mistake here. 00:08:33,179 --> 00:08:33,762 And it's true. 00:08:33,762 --> 00:08:35,480 I am making a bit of a mistake. 00:08:35,480 --> 00:08:36,809 One more example here. 00:08:36,809 --> 00:08:39,600 Let's say that I want to change directories into another directory. 00:08:39,600 --> 00:08:42,870 So I want to ls example6. 00:08:42,870 --> 00:08:44,810 There is, again, no example6 here. 00:08:44,810 --> 00:08:48,050 "ls cannot access example6, no such file or directory." 00:08:48,050 --> 00:08:50,180 Again, help50 might be able to help with this. 00:08:50,180 --> 00:08:52,446 So I'll preface it one more time. 00:08:52,446 --> 00:08:53,810 Are you sure example6 exists? 00:08:53,810 --> 00:08:55,370 Did you misspell example6? 00:08:55,370 --> 00:08:56,250 It doesn't exist. 00:08:56,250 --> 00:08:58,630 Maybe I had typed it wrong and I thought it was working. 00:08:58,630 --> 00:08:59,630 So it's just a reminder. 00:08:59,630 --> 00:09:00,791 Did you check that? 00:09:00,791 --> 00:09:02,040 Oh, maybe I had misspelled it. 00:09:02,040 --> 00:09:04,665 Maybe I meant to do something else, and then I can take a look. 00:09:04,665 --> 00:09:07,910 Now, help50 is a tool that is still in development. 00:09:07,910 --> 00:09:10,050 We actually have an open source GitHub repository. 00:09:10,050 --> 00:09:13,216 So as you go through the class and you become more comfortable, particularly 00:09:13,216 --> 00:09:16,700 as you start to learn Python, which is the tool that help50 is written in, 00:09:16,700 --> 00:09:20,540 you can actually head to CS50's public GitHub repositories and take a look 00:09:20,540 --> 00:09:22,640 and see what types of error messages that 00:09:22,640 --> 00:09:25,700 are a little more arcane that we're trying to catch and have help50 00:09:25,700 --> 00:09:28,070 explain in more human understandable terms 00:09:28,070 --> 00:09:30,666 so that if you want to contribute to that you actually can. 00:09:30,666 --> 00:09:32,540 And if you encounter an error that you're not 00:09:32,540 --> 00:09:37,280 getting, that help50 doesn't understand, and you want to report that error 00:09:37,280 --> 00:09:40,100 and hope that somebody else maybe can help match it, 00:09:40,100 --> 00:09:42,017 you can do that through that platform as well. 00:09:42,017 --> 00:09:43,808 So this is definitely a collaborative tool. 00:09:43,808 --> 00:09:46,700 And we welcome you to continue to contribute either solutions as you 00:09:46,700 --> 00:09:49,640 become more comfortable, or issues that we can try and resolve 00:09:49,640 --> 00:09:52,680 to make it a more robust tool. 00:09:52,680 --> 00:09:53,180 All right. 00:09:53,180 --> 00:09:55,740 So another tool that we have is one called eprintf. 00:09:55,740 --> 00:10:00,650 Now, it's really common when you are starting to debug your programs to kind 00:10:00,650 --> 00:10:03,230 of pepper them with printf statements. 00:10:03,230 --> 00:10:05,634 It's sort of like a sanity check where you're checking, 00:10:05,634 --> 00:10:06,800 OK, well, this line printed. 00:10:06,800 --> 00:10:08,710 And then I have some lines of code that run. 00:10:08,710 --> 00:10:09,650 And then this line printed. 00:10:09,650 --> 00:10:12,275 Like you're trying to figure out where things are going wrong. 00:10:12,275 --> 00:10:15,170 The trouble with printf is it doesn't necessarily tell you 00:10:15,170 --> 00:10:18,036 where the program is going wrong. 00:10:18,036 --> 00:10:20,660 You have to kind of go back and scroll through your source code 00:10:20,660 --> 00:10:23,160 to figure out which error message corresponds to that. 00:10:23,160 --> 00:10:24,590 That's not always that helpful. 00:10:24,590 --> 00:10:25,837 It's not a huge deal. 00:10:25,837 --> 00:10:28,170 But we have this tool that makes it a little bit easier. 00:10:28,170 --> 00:10:30,597 So it's called eprintf, which stands for error printf. 00:10:30,597 --> 00:10:32,930 And I'm just going to navigate into my eprintf directory 00:10:32,930 --> 00:10:35,120 where I have just one example file. 00:10:35,120 --> 00:10:38,490 I'm going to open that up here and show you what it does. 00:10:38,490 --> 00:10:39,759 So not much to this. 00:10:39,759 --> 00:10:40,925 I'm going to scroll up here. 00:10:40,925 --> 00:10:44,570 Basically what I'm doing is I'm asking the user to give me an integer. 00:10:44,570 --> 00:10:47,090 And then I actually get that integer from them. 00:10:47,090 --> 00:10:49,340 And then I have eprintf, integer obtained. 00:10:49,340 --> 00:10:50,840 Now, this means nothing to the user. 00:10:50,840 --> 00:10:53,540 It's an error message to make sure for me, 00:10:53,540 --> 00:10:56,870 as the person who's testing this program, that I got to this point 00:10:56,870 --> 00:10:58,142 in the program. 00:10:58,142 --> 00:11:00,350 And we'll see exactly what eprintf does that gives it 00:11:00,350 --> 00:11:02,474 a little bit of a leg up over printf, which is just 00:11:02,474 --> 00:11:03,860 going to display to the terminal. 00:11:03,860 --> 00:11:04,980 Then I'm doing a couple of different things. 00:11:04,980 --> 00:11:06,910 If x is less than 0, I'm going to print x is negative. 00:11:06,910 --> 00:11:08,951 If it's greater than zero, I print x is positive. 00:11:08,951 --> 00:11:10,347 Otherwise I print x is 0. 00:11:10,347 --> 00:11:12,680 And then I have one more eprintf call at the bottom here 00:11:12,680 --> 00:11:14,360 which is got through the program. 00:11:14,360 --> 00:11:17,720 So if I see that eprintf, that means that I've succeeded 00:11:17,720 --> 00:11:21,870 and I've gotten through every single line of the program without crashing. 00:11:21,870 --> 00:11:26,410 So let's just quickly compile this with make eprintf. 00:11:26,410 --> 00:11:29,410 And we'll try and run ./eprintf. 00:11:29,410 --> 00:11:30,730 Please give me an integer. 00:11:30,730 --> 00:11:33,390 Let's give it 50. 00:11:33,390 --> 00:11:35,080 And look at the little difference here. 00:11:35,080 --> 00:11:42,430 So instead of just printing out what I said, it tells me where it came from. 00:11:42,430 --> 00:11:45,256 So it tells me what line it came from and what file it came from. 00:11:45,256 --> 00:11:47,880 As we write more and more complex programs later in the course, 00:11:47,880 --> 00:11:50,430 we might write programs that span multiple .c files. 00:11:50,430 --> 00:11:52,380 We might have eprintfs throughout them. 00:11:52,380 --> 00:11:56,550 So it's just a useful way to figure out exactly from where in your program, 00:11:56,550 --> 00:12:00,090 or as things are going through, where in your program 00:12:00,090 --> 00:12:03,060 the error message that you're seeing, or sort of the printf 00:12:03,060 --> 00:12:05,541 prompt that you're seeing comes from. 00:12:05,541 --> 00:12:08,040 So it's definitely a good tool to familiarize yourself with, 00:12:08,040 --> 00:12:09,831 particularly earlier on where you might not 00:12:09,831 --> 00:12:12,075 need the more complex tools of a debugger, which 00:12:12,075 --> 00:12:13,260 we're going to talk about in a second. 00:12:13,260 --> 00:12:14,670 But you just want to get sort of a sanity check 00:12:14,670 --> 00:12:17,220 to make sure that things are working the way you expect them to. 00:12:17,220 --> 00:12:17,720 OK. 00:12:17,720 --> 00:12:20,790 And the third and final tool that we're going to cover in this video 00:12:20,790 --> 00:12:21,870 is debug50. 00:12:21,870 --> 00:12:25,920 Now, debug50 is a GUI or Graphical User Interface 00:12:25,920 --> 00:12:33,450 wrapper for a tool known as GDB, which is a very richly developed debugging 00:12:33,450 --> 00:12:34,380 platform. 00:12:34,380 --> 00:12:37,200 And it will really help you take a look underneath the hood, 00:12:37,200 --> 00:12:39,120 inspect what is going on in your program, 00:12:39,120 --> 00:12:42,510 and try and figure out where things might be going wrong. 00:12:42,510 --> 00:12:45,440 In this example we're going to cover three different buggy videos. 00:12:45,440 --> 00:12:47,565 And I'm going to show you how to use debug50 00:12:47,565 --> 00:12:50,190 to sort of give you some clues as to what you might need to do. 00:12:50,190 --> 00:12:54,210 So the first thing I'm going to do here is navigate into my debug50 directory 00:12:54,210 --> 00:12:58,670 where I have three source files and three programs that are previously 00:12:58,670 --> 00:12:59,170 compiled. 00:12:59,170 --> 00:13:00,690 So these have compiled. 00:13:00,690 --> 00:13:02,910 I don't need help50 to tell me what's going on here 00:13:02,910 --> 00:13:06,300 because I've already got the compiled binaries here. 00:13:06,300 --> 00:13:08,820 But there's something going wrong in these programs that 00:13:08,820 --> 00:13:10,230 is not what I expect. 00:13:10,230 --> 00:13:13,920 So the first thing I want to do is run debug1's program, 00:13:13,920 --> 00:13:16,470 and then we'll take a look at debug1's source code. 00:13:16,470 --> 00:13:18,744 And then we'll take a look at how debug50 00:13:18,744 --> 00:13:20,910 can give us a little bit more information about what 00:13:20,910 --> 00:13:22,506 might be going wrong here. 00:13:22,506 --> 00:13:23,880 So here's what we're going to do. 00:13:23,880 --> 00:13:26,671 We're going to go, and I'm going to clear my terminal really quick, 00:13:26,671 --> 00:13:31,050 and we're going to run debug1's binary. 00:13:31,050 --> 00:13:32,200 Provide a number. 00:13:32,200 --> 00:13:32,700 OK. 00:13:32,700 --> 00:13:34,590 I'll provide one. 00:13:34,590 --> 00:13:35,840 You gave a one. 00:13:35,840 --> 00:13:36,590 Seems pretty good. 00:13:36,590 --> 00:13:37,482 Let's try this again. 00:13:37,482 --> 00:13:38,190 Provide a number. 00:13:38,190 --> 00:13:40,110 I'll give it two. 00:13:40,110 --> 00:13:41,140 You gave a one. 00:13:41,140 --> 00:13:42,831 That's not right. 00:13:42,831 --> 00:13:43,330 Zero? 00:13:43,330 --> 00:13:44,470 You gave a one. 00:13:44,470 --> 00:13:48,120 So it's always saying, I gave a one. 00:13:48,120 --> 00:13:48,620 I did. 00:13:48,620 --> 00:13:49,560 I gave a one the first time. 00:13:49,560 --> 00:13:51,684 So let's maybe take a look at what's going on here. 00:13:51,684 --> 00:13:54,510 So I have my program. 00:13:54,510 --> 00:13:56,500 I'm providing a number. 00:13:56,500 --> 00:13:57,000 OK. 00:13:57,000 --> 00:13:57,660 That works. 00:13:57,660 --> 00:13:59,185 If x is one, say you gave a one. 00:13:59,185 --> 00:14:01,060 Otherwise, apparently I'm not doing anything. 00:14:01,060 --> 00:14:05,536 It's not supposed to print anything if I didn't give it a one. 00:14:05,536 --> 00:14:06,730 So that's weird. 00:14:06,730 --> 00:14:08,977 So at this point if you're familiar with the code 00:14:08,977 --> 00:14:10,560 you might see where the issue is here. 00:14:10,560 --> 00:14:12,200 But let's pretend that we don't. 00:14:12,200 --> 00:14:13,200 Or maybe you don't. 00:14:13,200 --> 00:14:16,130 And that's totally OK as well. 00:14:16,130 --> 00:14:19,850 This debug50 tool can hopefully give a little bit more information 00:14:19,850 --> 00:14:22,000 and we can see what's happening. 00:14:22,000 --> 00:14:23,824 So what I want to do is the first thing you 00:14:23,824 --> 00:14:25,740 need to do when you're working with a debugger 00:14:25,740 --> 00:14:27,825 like GDB is to provide a breakpoint. 00:14:27,825 --> 00:14:30,870 What a breakpoint is is basically your program 00:14:30,870 --> 00:14:33,810 will execute until it hits that line of code. 00:14:33,810 --> 00:14:37,470 And then it will stop, or break, and wait for something to happen. 00:14:37,470 --> 00:14:39,900 If you don't know where to break in your code, 00:14:39,900 --> 00:14:43,080 because you don't even know where the issue might be happening, 00:14:43,080 --> 00:14:45,192 it's totally reasonable to break at main. 00:14:45,192 --> 00:14:48,150 The way that you set a breakpoint is right here to the left of the line 00:14:48,150 --> 00:14:51,090 numbers you'll notice that my cursor turned into a little like pointer 00:14:51,090 --> 00:14:52,090 finger there. 00:14:52,090 --> 00:14:56,316 If you click once, you get this sort of red light, or a stop light. 00:14:56,316 --> 00:14:58,940 That's basically your indicator that you have set a breakpoint. 00:14:58,940 --> 00:15:04,230 So my program will compile, and it will run until it gets to line six. 00:15:04,230 --> 00:15:06,510 At which point it's going to kind of freeze. 00:15:06,510 --> 00:15:09,570 And from there I can make very slow steps through my program. 00:15:09,570 --> 00:15:12,300 Usually when we're running our program it's like you compile it, 00:15:12,300 --> 00:15:13,710 and it's done. 00:15:13,710 --> 00:15:15,942 Here we can really force it to slow down, and look 00:15:15,942 --> 00:15:18,150 what it's doing line, by line, by line, and see if we 00:15:18,150 --> 00:15:21,089 can see where the issue might lie. 00:15:21,089 --> 00:15:22,130 So I've set a breakpoint. 00:15:22,130 --> 00:15:24,240 Now I need to run debug50. 00:15:24,240 --> 00:15:29,150 debug50 ./debug1. 00:15:29,150 --> 00:15:32,270 Cause that's the name of the program that I wanted to test. 00:15:32,270 --> 00:15:34,110 Hit Enter. 00:15:34,110 --> 00:15:36,797 And if you've watched our CS50 IDE tutorial introduction video 00:15:36,797 --> 00:15:38,630 you noticed I talked about the debugger tab. 00:15:38,630 --> 00:15:41,940 You'll notice the debugger tab on the right has popped open. 00:15:41,940 --> 00:15:43,940 And I'm giving a little bit of information here. 00:15:43,940 --> 00:15:45,869 I have information about the call stacks. 00:15:45,869 --> 00:15:47,660 So if I had multiple functions being called 00:15:47,660 --> 00:15:49,785 it would tell me which function I'm in at the time, 00:15:49,785 --> 00:15:52,460 and which functions are waiting for stuff to happen. 00:15:52,460 --> 00:15:54,430 Local variables in my program. 00:15:54,430 --> 00:15:55,340 There are values. 00:15:55,340 --> 00:15:57,290 What type they are, and so on. 00:15:57,290 --> 00:16:00,430 Really useful stuff. 00:16:00,430 --> 00:16:02,110 And my program has frozen, right. 00:16:02,110 --> 00:16:04,902 It has not printed out "please provide a number." 00:16:04,902 --> 00:16:06,610 It's just waiting for me to do something. 00:16:06,610 --> 00:16:09,971 And the way I can control what my program does is up here at the top. 00:16:09,971 --> 00:16:12,970 I have resume, which is basically just going to speed through my program 00:16:12,970 --> 00:16:15,520 again, ignoring any more breakpoints. 00:16:15,520 --> 00:16:21,829 I have step over, which is going to move one line ahead. 00:16:21,829 --> 00:16:24,370 And generally you're going to want to step over any functions 00:16:24,370 --> 00:16:27,299 that you did not write, because if you step into them, which 00:16:27,299 --> 00:16:30,340 is the next example, it's actually going to go and look at printf's code, 00:16:30,340 --> 00:16:32,950 and start executing printf's code one line at a time. 00:16:32,950 --> 00:16:35,140 And we can probably assume that printf is OK. 00:16:35,140 --> 00:16:37,660 And we can probably assume that getint, for example, is OK. 00:16:37,660 --> 00:16:39,160 So we don't need to step into those. 00:16:39,160 --> 00:16:40,180 We can step over them. 00:16:40,180 --> 00:16:43,480 If you're going into a block, for example, like an if, or a function 00:16:43,480 --> 00:16:45,470 that you wrote, you might want to step into it, 00:16:45,470 --> 00:16:50,090 unless you happen to know for sure that it's not an issue in that function. 00:16:50,090 --> 00:16:53,030 So you can start to proceed through those a line at a time. 00:16:53,030 --> 00:16:54,537 And then, lastly, there's step out. 00:16:54,537 --> 00:16:55,870 We're not in anything right now. 00:16:55,870 --> 00:16:57,640 So we can't step out. 00:16:57,640 --> 00:16:59,667 But if you step into a function and you realize, 00:16:59,667 --> 00:17:02,000 oh, I really shouldn't have done this, you can step out, 00:17:02,000 --> 00:17:03,430 which will just proceed through the rest of the function, 00:17:03,430 --> 00:17:06,161 and then pick up again at the next logical spot. 00:17:06,161 --> 00:17:08,869 So what I want to do here is start to proceed one line at a time. 00:17:08,869 --> 00:17:10,828 So I want this to print out "provide a number." 00:17:10,828 --> 00:17:13,577 So I'm going to step over this line, which is going to execute it. 00:17:13,577 --> 00:17:15,800 You can see it at the terminal there at the bottom. 00:17:15,800 --> 00:17:17,849 Then it's prompting me to provide a number. 00:17:17,849 --> 00:17:19,740 So I'll give it a three. 00:17:19,740 --> 00:17:20,627 One seems to work. 00:17:20,627 --> 00:17:21,960 So I'm going to give it a three. 00:17:21,960 --> 00:17:23,849 And I'll hit Enter. 00:17:23,849 --> 00:17:27,420 And then I will again step over. 00:17:27,420 --> 00:17:30,000 If x equals one printf. 00:17:30,000 --> 00:17:31,260 You gave a one. 00:17:31,260 --> 00:17:33,570 So I kind of want to step into this. 00:17:33,570 --> 00:17:35,820 And in particular, notice what's going to happen here. 00:17:35,820 --> 00:17:38,490 Notice that right now it says my variable x 00:17:38,490 --> 00:17:41,040 has a value of three, which is what I expect. 00:17:41,040 --> 00:17:46,290 But as I step into this, the value of x has changed to one. 00:17:46,290 --> 00:17:47,880 It's no longer three. 00:17:47,880 --> 00:17:50,040 So this statement is now true. 00:17:50,040 --> 00:17:51,720 It says, well, x is one. 00:17:51,720 --> 00:17:53,580 So you gave a one. 00:17:53,580 --> 00:17:56,100 And if I step over, that is what it will do. 00:17:56,100 --> 00:17:56,950 You gave a one. 00:17:56,950 --> 00:18:02,040 And if I stop one more time, the program finishes executing. 00:18:02,040 --> 00:18:04,500 Did you happen to see what the error there was? 00:18:04,500 --> 00:18:06,270 It's a silly little syntax thing. 00:18:06,270 --> 00:18:09,210 But I used a single equal sign instead of a double equal sign. 00:18:09,210 --> 00:18:13,200 So what I really did here is I assigned x to be one. 00:18:13,200 --> 00:18:18,090 Regardless of what x was at this point, I said x is equal to one. 00:18:18,090 --> 00:18:22,470 I assigned x to one, when I really meant to do this. 00:18:22,470 --> 00:18:25,680 If x equals equals one. 00:18:25,680 --> 00:18:30,390 And now let's just save this program really quickly. 00:18:30,390 --> 00:18:33,270 And we'll recompile it, because we have to recompile 00:18:33,270 --> 00:18:35,625 a program if we want to rerun it. 00:18:35,625 --> 00:18:38,250 Use equals to turn this comparison into an equality assignment. 00:18:38,250 --> 00:18:39,920 Now, the reason that this works is because I had put 00:18:39,920 --> 00:18:41,503 this extra set of parentheses in here. 00:18:41,503 --> 00:18:43,920 Generally if you tried to do this it wouldn't work. 00:18:43,920 --> 00:18:46,044 But I had to force it for purposes of this example. 00:18:46,044 --> 00:18:48,151 So I had to get rid of those parentheses as well. 00:18:48,151 --> 00:18:50,150 We'll try one more time to compile this program. 00:18:50,150 --> 00:18:51,440 Now it compiled successfully. 00:18:51,440 --> 00:18:53,000 We'll clear our terminal window. 00:18:53,000 --> 00:18:54,920 And let's try and debug50 one more time, just 00:18:54,920 --> 00:18:59,210 to make sure that everything is working the way we expect. 00:18:59,210 --> 00:19:01,160 We still have our breakpoint set at line six. 00:19:01,160 --> 00:19:04,700 So it's still going to freeze at the first possible opportunity after that. 00:19:04,700 --> 00:19:06,890 I want to step over this to provide a number. 00:19:06,890 --> 00:19:10,010 I'll give it three again. 00:19:10,010 --> 00:19:11,020 Step over. 00:19:11,020 --> 00:19:12,020 x is now equal to three. 00:19:12,020 --> 00:19:13,790 You can see here on the right. 00:19:13,790 --> 00:19:15,585 Now, let's step into this. 00:19:18,190 --> 00:19:19,071 Can't step into it. 00:19:19,071 --> 00:19:19,570 Why? 00:19:19,570 --> 00:19:21,110 Because x is not one anymore. 00:19:21,110 --> 00:19:23,770 So that next line of code on line 13 there 00:19:23,770 --> 00:19:26,960 is not going to execute because the condition is no longer true. 00:19:26,960 --> 00:19:28,930 So before I was assigning x to be one. 00:19:28,930 --> 00:19:30,379 And that's why it would go in. 00:19:30,379 --> 00:19:32,920 And thanks to debug50 I was able to see, oh, wait, this three 00:19:32,920 --> 00:19:34,874 is unexpectedly changing into a one. 00:19:34,874 --> 00:19:37,040 Maybe there's something going on wrong in that area. 00:19:37,040 --> 00:19:40,720 So that's one way that debug50 was able to help isolate where in the program 00:19:40,720 --> 00:19:43,520 things were going awry. 00:19:43,520 --> 00:19:44,020 All right. 00:19:44,020 --> 00:19:46,150 So I'm going to hit Resume here just to end the program, 00:19:46,150 --> 00:19:47,540 have it finish doing its thing. 00:19:47,540 --> 00:19:50,090 Didn't print anything because we didn't have a one. 00:19:50,090 --> 00:19:52,660 And now let's take a look at program number two. 00:19:52,660 --> 00:19:55,640 So I'll clear my terminal. 00:19:55,640 --> 00:20:00,450 And let's try and execute the debug2 program. 00:20:00,450 --> 00:20:03,330 "What percentage grade did you get as a number?" 00:20:03,330 --> 00:20:08,400 Well, let's say maybe I wasn't doing so great in CS50 and I got a 50%. 00:20:08,400 --> 00:20:09,520 My grade is an E. 00:20:09,520 --> 00:20:10,020 OK. 00:20:10,020 --> 00:20:13,590 But let's say maybe I'm doing a little bit better and I got a 75. 00:20:13,590 --> 00:20:18,257 So that should hopefully be like a C. Eh, I got an E. 00:20:18,257 --> 00:20:18,840 Wait a minute. 00:20:18,840 --> 00:20:21,480 What if I got like an A, I got everything? 00:20:21,480 --> 00:20:22,195 E. 00:20:22,195 --> 00:20:24,820 Well, again, this isn't doing exactly what I expected it to do. 00:20:24,820 --> 00:20:26,310 So let's take a look at the source code. 00:20:26,310 --> 00:20:28,685 And then let's take a look at debug50 and see if maybe it 00:20:28,685 --> 00:20:30,219 can give us some clues here. 00:20:30,219 --> 00:20:32,010 So I'll open up the source code for debug2. 00:20:32,010 --> 00:20:33,650 And I'll just close this one here. 00:20:33,650 --> 00:20:36,460 And I'll also just clear the terminal screen one more time. 00:20:36,460 --> 00:20:36,960 All right. 00:20:36,960 --> 00:20:39,293 So what percentage of the grade did you get as a number? 00:20:39,293 --> 00:20:40,140 Get an integer. 00:20:40,140 --> 00:20:42,098 What's happening here on line eight is I'm just 00:20:42,098 --> 00:20:46,080 transforming whatever the user gave me into a multiple of 10, 00:20:46,080 --> 00:20:48,420 so that divided by 10 times 10, that's a trick that 00:20:48,420 --> 00:20:49,836 works because of integer division. 00:20:49,836 --> 00:20:52,050 But say the user gives me 93. 00:20:52,050 --> 00:20:54,970 93 divided by 10 is nine, not 9.3. 00:20:54,970 --> 00:20:56,310 Remember, its integer division. 00:20:56,310 --> 00:20:58,530 And then 9 times 10 is 90. 00:20:58,530 --> 00:21:03,060 So I'm just basically dropping off the ones place of every number 00:21:03,060 --> 00:21:06,040 here and just transforming it into a multiple of 10. 00:21:06,040 --> 00:21:08,285 And then I have a letter character for a grade. 00:21:08,285 --> 00:21:09,930 It will get stored there. 00:21:09,930 --> 00:21:11,779 And then I'm using a switch statement, which 00:21:11,779 --> 00:21:15,070 is one form of conditional statement, to look over the different possibilities. 00:21:15,070 --> 00:21:19,630 So if I have a 90 or a 100 after executing lines seven, eight, 00:21:19,630 --> 00:21:24,750 grade should be an A. If I have an 80, it should be a B, a C, a D, and an E, 00:21:24,750 --> 00:21:26,730 depending on what my scores are. 00:21:26,730 --> 00:21:29,551 But it seems like every time I'm doing this I'm getting an E. 00:21:29,551 --> 00:21:31,800 And, again, if you're familiar with switch statements, 00:21:31,800 --> 00:21:33,790 you might see what the issue is here. 00:21:33,790 --> 00:21:35,550 And if you're not familiar with switch statements, that's OK. 00:21:35,550 --> 00:21:38,258 Because switch statements are a little bit strange the first time 00:21:38,258 --> 00:21:38,970 you use them. 00:21:38,970 --> 00:21:43,249 But debug50 can help us figure out what is happening here. 00:21:43,249 --> 00:21:46,290 So first thing we got to do, of course, is we got to set that breakpoint. 00:21:46,290 --> 00:21:49,020 So I got to figure out where I want to set it. 00:21:49,020 --> 00:21:51,900 Well, it looks like I might have already set it here at line 11. 00:21:51,900 --> 00:21:55,290 And that seems like a fair enough place to do it. 00:21:55,290 --> 00:21:58,360 So let's set our breakpoint there. 00:21:58,360 --> 00:22:01,500 So our program will not freeze and pop open for us 00:22:01,500 --> 00:22:04,840 until we get to that point in the code. 00:22:04,840 --> 00:22:09,440 So we'll use debug50 on the debug program number two. 00:22:12,009 --> 00:22:14,300 "What percentage of the grade did you get as a number?" 00:22:14,300 --> 00:22:17,290 So let's say I got 100. 00:22:17,290 --> 00:22:18,730 And now we're frozen. 00:22:18,730 --> 00:22:22,372 And notice over here, grade has been set to negative one. 00:22:22,372 --> 00:22:23,330 There's no value there. 00:22:23,330 --> 00:22:26,650 But that makes sense, cause we haven't assigned grade equals something yet. 00:22:26,650 --> 00:22:29,000 Percent is 100 and 10th is 100. 00:22:29,000 --> 00:22:30,670 So we have the value we're expecting. 00:22:30,670 --> 00:22:36,920 10th is 100, which means when we get to line 13, grade A should get triggered. 00:22:36,920 --> 00:22:42,224 So let's step in one line at a time. 00:22:42,224 --> 00:22:45,050 All right. 00:22:45,050 --> 00:22:51,310 So notice that my grade is A. And then it's B. 00:22:51,310 --> 00:22:59,140 And then it's C. And then it's D. And then it's E. And then if I step over, 00:22:59,140 --> 00:23:01,560 that's what now gets printed. 00:23:01,560 --> 00:23:03,470 And that's not what I expect. 00:23:03,470 --> 00:23:06,980 So it seems like by using debug50 to step slowly 00:23:06,980 --> 00:23:08,960 through my program, what was happening is 00:23:08,960 --> 00:23:12,680 I wasn't just triggering the one case that I wanted to hit. 00:23:12,680 --> 00:23:16,160 I seemed to be hitting all of the different cases. 00:23:16,160 --> 00:23:17,730 And the grade kept changing. 00:23:17,730 --> 00:23:19,146 It started out at the right thing. 00:23:19,146 --> 00:23:22,730 It started out as A. And then it became B, and a C, and a D, and an E. 00:23:22,730 --> 00:23:25,910 And the reason for that, and again, we'll cover this on our video 00:23:25,910 --> 00:23:27,950 on conditionals if you haven't seen it already, 00:23:27,950 --> 00:23:33,140 is that at the end of every case option for a switch I needed to have a break. 00:23:33,140 --> 00:23:36,790 I only ever want one of these things to be true. 00:23:36,790 --> 00:23:39,080 Now, it's true that you might end up in a situation 00:23:39,080 --> 00:23:41,830 where you actually want the behavior of falling through the cases, 00:23:41,830 --> 00:23:43,100 as it's known. 00:23:43,100 --> 00:23:44,570 But that's not what I want here. 00:23:44,570 --> 00:23:47,630 I want explicitly to be assigned one value. 00:23:47,630 --> 00:23:50,220 And then I don't want to look at the rest of the options. 00:23:50,220 --> 00:23:52,094 So what happened here is I just fell through. 00:23:52,094 --> 00:23:54,694 I kept executing every line of code from case 100 down. 00:23:54,694 --> 00:23:57,360 If I had started out at 80, it would have given me a B, and then 00:23:57,360 --> 00:24:00,200 a C, and then a D, and then an E. And if I started out at like a 60, 00:24:00,200 --> 00:24:03,205 it would have given me a D and then an E. 00:24:03,205 --> 00:24:04,080 So I don't want that. 00:24:04,080 --> 00:24:08,790 So I have to include break statements at the end of all of my different options 00:24:08,790 --> 00:24:09,970 within the switch. 00:24:09,970 --> 00:24:15,240 And if I save this and I recompile it, and I clear my terminal 00:24:15,240 --> 00:24:20,470 and run it one more time, if I get 100, now I have an A. All right. 00:24:20,470 --> 00:24:21,030 That's good. 00:24:21,030 --> 00:24:24,050 If I get an 80, I have a B, and so on. 00:24:24,050 --> 00:24:26,950 And so, again, by using the tools this time 00:24:26,950 --> 00:24:30,614 of seeing that I was hitting all of these different lines of code, 00:24:30,614 --> 00:24:32,530 not necessarily that variables were changing-- 00:24:32,530 --> 00:24:34,821 although it was useful to see that A was turning into B 00:24:34,821 --> 00:24:38,290 and turning into C. What was more useful for me there anyway was seeing 00:24:38,290 --> 00:24:40,522 that I was hitting all of these lines of code 00:24:40,522 --> 00:24:41,980 that I shouldn't have been hitting. 00:24:41,980 --> 00:24:44,104 I should have only been hitting the very one, which 00:24:44,104 --> 00:24:46,420 was case 90, colon, case 100 colon. 00:24:46,420 --> 00:24:50,110 Because that was what I had typed in, a 90 or a 100. 00:24:50,110 --> 00:24:52,932 So it was strange that I ended up falling through. 00:24:52,932 --> 00:24:54,640 And being able to see it go line by line, 00:24:54,640 --> 00:24:58,750 as opposed to just the program running so quickly because it's so short, 00:24:58,750 --> 00:25:00,029 that was a good clue for me. 00:25:00,029 --> 00:25:01,320 We have one more buggy program. 00:25:01,320 --> 00:25:03,653 And let's take a look at that one and see if debug50 can 00:25:03,653 --> 00:25:06,330 help us figure that one out as well. 00:25:06,330 --> 00:25:09,480 So I'll close this code window here. 00:25:09,480 --> 00:25:11,880 And let's run debug3. 00:25:11,880 --> 00:25:13,940 How many stars? 00:25:13,940 --> 00:25:15,150 Five. 00:25:15,150 --> 00:25:16,290 Give me six. 00:25:16,290 --> 00:25:17,550 How many stars? 00:25:17,550 --> 00:25:18,922 Zero. 00:25:18,922 --> 00:25:20,810 it gives me one. 00:25:20,810 --> 00:25:21,960 How many stars? 00:25:21,960 --> 00:25:23,450 40. 00:25:23,450 --> 00:25:26,860 Well, I'm not going to count that, but it's 41 is what it is. 00:25:26,860 --> 00:25:28,990 So I'm getting a few too many stars. 00:25:28,990 --> 00:25:32,980 But if I look at my debug3 source code, I'm going from zero to x, 00:25:32,980 --> 00:25:35,860 and I'm printing out a star for every time. 00:25:35,860 --> 00:25:39,020 So it seems like that should be working just fine, but it's not. 00:25:39,020 --> 00:25:43,780 So maybe the debugger can help us figure this out a little bit more cleanly. 00:25:43,780 --> 00:25:44,710 So let's pop it open. 00:25:44,710 --> 00:25:46,690 Let's first set a breakpoint. 00:25:46,690 --> 00:25:50,277 It seems like the integer part is maybe not working. 00:25:50,277 --> 00:25:52,360 So instead of setting it to breakpoint after that, 00:25:52,360 --> 00:25:55,420 maybe it somehow is turning five into six? 00:25:55,420 --> 00:25:55,979 I don't know. 00:25:55,979 --> 00:25:57,520 Let's set our breakpoint before that. 00:25:57,520 --> 00:25:59,170 Let's just set our breakpoint right at main. 00:25:59,170 --> 00:26:00,490 And there was a breakpoint here. 00:26:00,490 --> 00:26:01,531 We'll just get rid of it. 00:26:01,531 --> 00:26:04,252 You can double click on a breakpoint to make it go away if you 00:26:04,252 --> 00:26:05,710 don't want to use that one anymore. 00:26:05,710 --> 00:26:06,940 And you can also set multiple breakpoints. 00:26:06,940 --> 00:26:08,660 We're not doing it in these examples. 00:26:08,660 --> 00:26:10,630 But I could set a breakpoint at first spot, 00:26:10,630 --> 00:26:12,820 and then maybe another one a little bit later on. 00:26:12,820 --> 00:26:15,440 It would stop at that point as well. 00:26:15,440 --> 00:26:15,940 All right. 00:26:15,940 --> 00:26:17,470 So let's try and compile this. 00:26:17,470 --> 00:26:19,630 So really quickly recompile. 00:26:19,630 --> 00:26:24,060 And then we'll run debug50 to take a look 00:26:24,060 --> 00:26:25,560 at what's happening in this program. 00:26:29,720 --> 00:26:30,765 All right. 00:26:30,765 --> 00:26:31,390 How many stars? 00:26:31,390 --> 00:26:32,556 So, again, we broke at main. 00:26:32,556 --> 00:26:34,770 So it's going to freeze at line six and wait. 00:26:34,770 --> 00:26:38,130 If I step over this line, it will print out how many stars. 00:26:38,130 --> 00:26:41,330 Let's say that I want five. 00:26:41,330 --> 00:26:43,560 Then we'll step over this. 00:26:43,560 --> 00:26:46,670 Because we don't need to step in to get in presumably. 00:26:46,670 --> 00:26:53,350 And when we get through, I's value is 32,677, which is actually OK. 00:26:53,350 --> 00:26:56,260 It hasn't been set yet, because line nine has not executed. 00:26:56,260 --> 00:26:57,670 But x is five. 00:26:57,670 --> 00:26:59,740 It didn't somehow transform into six. 00:26:59,740 --> 00:27:02,860 So what I now know at least is that my error somewhere 00:27:02,860 --> 00:27:04,450 happens from line nine down. 00:27:04,450 --> 00:27:05,310 It's not line six. 00:27:05,310 --> 00:27:06,430 It's not line seven. 00:27:06,430 --> 00:27:09,730 It's got to be after that, because x has the correct value. 00:27:09,730 --> 00:27:10,290 It has five. 00:27:10,290 --> 00:27:13,300 It didn't somehow get transformed into six. 00:27:13,300 --> 00:27:15,610 But I's value is 32,767. 00:27:15,610 --> 00:27:16,570 This is a red herring. 00:27:16,570 --> 00:27:17,320 This is not a bug. 00:27:17,320 --> 00:27:19,630 Like I said, line nine has not executed yet. 00:27:19,630 --> 00:27:23,430 Once line nine executes then I will be set at least to zero, 00:27:23,430 --> 00:27:24,520 as we'll see right now. 00:27:24,520 --> 00:27:26,030 So we'll step into this loop. 00:27:26,030 --> 00:27:28,510 Notice now I is zero, which is what we expect. 00:27:28,510 --> 00:27:29,890 Then it will print a star. 00:27:29,890 --> 00:27:32,806 I'm going to step over that, because I don't want to step into printf. 00:27:32,806 --> 00:27:34,170 So we'll step over. 00:27:34,170 --> 00:27:37,550 Notice that it printed one star to the terminal. 00:27:37,550 --> 00:27:38,640 Step again. 00:27:38,640 --> 00:27:40,204 I is now one. 00:27:40,204 --> 00:27:41,120 That's what we expect. 00:27:41,120 --> 00:27:43,250 We went through one iteration of the loop. 00:27:43,250 --> 00:27:44,935 I incremented by one. 00:27:44,935 --> 00:27:46,080 I'm going to step over. 00:27:46,080 --> 00:27:46,820 Print. 00:27:46,820 --> 00:27:49,020 OK. 00:27:49,020 --> 00:27:51,360 Two. 00:27:51,360 --> 00:27:53,650 Three. 00:27:53,650 --> 00:27:55,782 Four. 00:27:55,782 --> 00:27:57,740 Now, at this point I should be breaking, right. 00:27:57,740 --> 00:28:01,930 I'm going from I is equal to zero to I is less than or equal to x. 00:28:01,930 --> 00:28:02,430 Uh-oh. 00:28:02,430 --> 00:28:04,460 I see my bug now already, right. 00:28:04,460 --> 00:28:08,840 I'm counting I is equal to zero to I is less than or equal to x. 00:28:08,840 --> 00:28:13,400 So I saw it even before debug50 saw it for me. 00:28:13,400 --> 00:28:18,320 But it's true if I step into this loop, now I's value is five. 00:28:18,320 --> 00:28:22,152 So it should have stopped if I did what I intended, which is I is less than x. 00:28:22,152 --> 00:28:23,860 But it actually went into the loop, which 00:28:23,860 --> 00:28:27,670 means it's going to execute this line of code again. 00:28:27,670 --> 00:28:35,370 And now it's true that if I step into this, I goes away, right. 00:28:35,370 --> 00:28:39,530 Because if I became six, this loop would no longer run. 00:28:39,530 --> 00:28:40,464 So it goes away. 00:28:40,464 --> 00:28:41,630 And I break out of the loop. 00:28:41,630 --> 00:28:42,890 And I jump down to line 12. 00:28:42,890 --> 00:28:45,560 But I've printed out six stars instead of five. 00:28:45,560 --> 00:28:48,500 Now, again, these examples are a little bit contrived 00:28:48,500 --> 00:28:52,800 for the purposes of showing you how to use the debugger. 00:28:52,800 --> 00:28:56,540 It's not supposed to necessarily find the bug for you. 00:28:56,540 --> 00:29:00,260 But it's supposed to slow the computer down enough that you 00:29:00,260 --> 00:29:02,605 can see the steps that it's doing. 00:29:02,605 --> 00:29:06,260 So the values on the right, being able to track what values variables 00:29:06,260 --> 00:29:08,150 have is useful. 00:29:08,150 --> 00:29:12,950 Also I didn't show this, but you can actually change the value of variables 00:29:12,950 --> 00:29:13,450 if you want. 00:29:13,450 --> 00:29:15,434 I could say x is equal to 23. 00:29:15,434 --> 00:29:17,600 I could do this in the middle of my program running, 00:29:17,600 --> 00:29:19,670 between doing different lines to change things, 00:29:19,670 --> 00:29:21,860 to see if the behavior is affected in any way. 00:29:21,860 --> 00:29:23,390 It wouldn't have been that useful here because I've already 00:29:23,390 --> 00:29:24,349 broken out of the loop. 00:29:24,349 --> 00:29:27,139 But if I wanted to somehow make it artificially print more and more 00:29:27,139 --> 00:29:29,310 because I haven't figured it out yet, I can do that. 00:29:29,310 --> 00:29:31,770 You can do that with any local variable there as well. 00:29:31,770 --> 00:29:34,430 You can use this to inspect strings and arrays as well, 00:29:34,430 --> 00:29:35,840 which we're not going to get into here, because this is just 00:29:35,840 --> 00:29:37,970 supposed to be a general tutorial. 00:29:37,970 --> 00:29:41,180 But, again, the goal is not so much to be, here's the bug. 00:29:41,180 --> 00:29:47,330 It's to slow things down enough that you can see exactly what the computer is 00:29:47,330 --> 00:29:50,120 doing, and see if at any point it deviates 00:29:50,120 --> 00:29:52,160 from what you expect it to be doing. 00:29:52,160 --> 00:29:54,710 And that's what all these debugging tools are used for, 00:29:54,710 --> 00:29:57,230 particularly this GDB based one called debug50. 00:29:57,230 --> 00:29:58,050 But eprintf. 00:29:58,050 --> 00:30:00,800 Make sure that your program is printing out 00:30:00,800 --> 00:30:03,130 sort of sanity check messages in the right spot. 00:30:03,130 --> 00:30:06,710 help50 is supposed to give you some clues about where 00:30:06,710 --> 00:30:09,260 you might have compile time errors. 00:30:09,260 --> 00:30:12,050 And debug50 is supposed to help you figure out 00:30:12,050 --> 00:30:13,630 where your runtime errors are. 00:30:13,630 --> 00:30:15,671 So use all these tools in conjunction, and you'll 00:30:15,671 --> 00:30:18,402 be well on your way to debugging code like an expert in no time. 00:30:18,402 --> 00:30:19,490 I'm Doug Lloyd. 00:30:19,490 --> 00:30:21,300 This is CS50.