1 00:00:00,500 --> 00:00:03,150 DOUG LLOYD: So if you're anything like me, when you write code 2 00:00:03,150 --> 00:00:06,240 it's not always going to be perfect. 3 00:00:06,240 --> 00:00:08,820 There's usually going to be something wrong with it. 4 00:00:08,820 --> 00:00:11,550 And that is known as writing bugs. 5 00:00:11,550 --> 00:00:13,680 And part of being a computer programmer is 6 00:00:13,680 --> 00:00:16,604 learning how to debug, or remove the bugs, from programs. 7 00:00:16,604 --> 00:00:19,020 And there are a lot of different techniques and strategies 8 00:00:19,020 --> 00:00:20,620 that one might use to do this. 9 00:00:20,620 --> 00:00:22,578 And what I want to do in this video is show you 10 00:00:22,578 --> 00:00:25,590 three of the tools that are baked into CS50 IDE 11 00:00:25,590 --> 00:00:28,680 that you can use to help with your debugging, 12 00:00:28,680 --> 00:00:31,639 or help trying to figure out what's going on in your system. 13 00:00:31,639 --> 00:00:34,680 And these three tools, which I'm going to just display the names of here, 14 00:00:34,680 --> 00:00:39,490 are known as debug50, eprintf, and help50. 15 00:00:39,490 --> 00:00:42,150 We're actually going to cover those in reverse order. 16 00:00:42,150 --> 00:00:43,650 So we're going to start with help50. 17 00:00:43,650 --> 00:00:45,858 So I have a couple of files pre-configured in my IDE. 18 00:00:45,858 --> 00:00:49,710 I'm going to navigate into my help50 directory. 19 00:00:49,710 --> 00:00:52,470 And just clear the terminal window here. 20 00:00:52,470 --> 00:00:54,750 And what help50 basically does, it is designed 21 00:00:54,750 --> 00:00:58,150 to be sort of a virtual teaching fellow of sorts. 22 00:00:58,150 --> 00:01:01,890 It basically is trying to give you clues and hints about what might be going on 23 00:01:01,890 --> 00:01:05,430 in your program or when you're trying to work with your program 24 00:01:05,430 --> 00:01:08,310 and something goes wrong without just giving you the answer outright. 25 00:01:08,310 --> 00:01:11,185 So it's trying to nudge you along in the right direction in the hopes 26 00:01:11,185 --> 00:01:14,130 that it's an issue that, with a little bit of encountering and having 27 00:01:14,130 --> 00:01:16,713 the computers sort of give you a little bit of back and forth, 28 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. 29 00:01:20,520 --> 00:01:23,010 So I have a couple of example programs here. 30 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. 31 00:01:27,170 --> 00:01:31,300 So let's try and make example one. 32 00:01:31,300 --> 00:01:31,977 Error. 33 00:01:31,977 --> 00:01:34,060 So this is where help50 is going to come in handy. 34 00:01:34,060 --> 00:01:37,000 Generally it's going to be used when you're working. 35 00:01:37,000 --> 00:01:40,360 It's not so much a bug in your program that is 36 00:01:40,360 --> 00:01:42,430 during runtime, a runtime error. 37 00:01:42,430 --> 00:01:45,580 This is going to be a logical bug, or some kind 38 00:01:45,580 --> 00:01:48,950 of bug that prevents your program from being compiled 39 00:01:48,950 --> 00:01:52,240 is going to be the most common use case of help50. 40 00:01:52,240 --> 00:01:55,750 So here I'm getting told I'm implicitly declaring library function 41 00:01:55,750 --> 00:01:57,214 printf with blah, blah, blah. 42 00:01:57,214 --> 00:01:58,630 There's a whole lot of text there. 43 00:01:58,630 --> 00:02:02,479 Now, what help50 tries to do is it looks at that error message for you. 44 00:02:02,479 --> 00:02:04,270 And if there are multiple ones it will look 45 00:02:04,270 --> 00:02:05,800 at the first error message for you. 46 00:02:05,800 --> 00:02:08,979 And it will try and translate that kind of arcane language 47 00:02:08,979 --> 00:02:12,144 into something a little more, hopefully, intuitive to use. 48 00:02:12,144 --> 00:02:14,310 And the way we use help50 is pretty straightforward. 49 00:02:14,310 --> 00:02:20,950 We first type help50, and then we do exactly the command we tried to do. 50 00:02:20,950 --> 00:02:23,320 So in this case it's help50, make example1. 51 00:02:23,320 --> 00:02:26,470 Let's see if maybe help50 can give me a little more information about what 52 00:02:26,470 --> 00:02:29,800 I might be doing wrong in my program. 53 00:02:29,800 --> 00:02:30,930 So I run it again. 54 00:02:30,930 --> 00:02:34,020 Now, I'm getting this sort of hint from the virtual TF, 55 00:02:34,020 --> 00:02:35,790 which is written here in yellow. 56 00:02:35,790 --> 00:02:38,790 "Did you forget to #include stdio.h in which printf 57 00:02:38,790 --> 00:02:40,400 is declared atop your file?" 58 00:02:40,400 --> 00:02:41,400 Well, let's take a look. 59 00:02:41,400 --> 00:02:45,760 So in example 1.c, it looks like I did kind of forget to do that. 60 00:02:45,760 --> 00:02:51,310 So if I just go ahead and add that, and I save, 61 00:02:51,310 --> 00:02:55,580 and I try and make example one again maybe. 62 00:02:55,580 --> 00:02:56,850 Hey, it compiled. 63 00:02:56,850 --> 00:02:57,690 It worked just fine. 64 00:02:57,690 --> 00:03:00,975 So I can now run the example1 program, hello world. 65 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. 66 00:03:04,100 --> 00:03:06,067 So it kind of ran into a new line like that. 67 00:03:06,067 --> 00:03:06,650 But that's OK. 68 00:03:06,650 --> 00:03:09,390 That's something I can go ahead and fix pretty easily. 69 00:03:09,390 --> 00:03:11,744 So let's try and compile example two. 70 00:03:11,744 --> 00:03:14,660 And we'll go through this again where we won't look at the source code 71 00:03:14,660 --> 00:03:15,400 beforehand. 72 00:03:15,400 --> 00:03:18,350 We'll just try and compile it, thinking we're pretty close, 73 00:03:18,350 --> 00:03:19,290 and see what happens. 74 00:03:19,290 --> 00:03:23,310 So we'll try and make example2. 75 00:03:23,310 --> 00:03:23,810 Oh. 76 00:03:23,810 --> 00:03:25,340 Seven errors generated. 77 00:03:25,340 --> 00:03:26,331 That's not good. 78 00:03:26,331 --> 00:03:27,830 But, again, help50 can help us here. 79 00:03:27,830 --> 00:03:29,538 And what it's going to do in this case is 80 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. 81 00:03:33,090 --> 00:03:35,689 Now, oftentimes when you get a lot of errors from compiling 82 00:03:35,689 --> 00:03:37,980 it's not necessarily that I've done seven things wrong. 83 00:03:37,980 --> 00:03:39,729 In fact, if you look at the program you'll 84 00:03:39,729 --> 00:03:42,320 see that it's not that many lines of code when we do. 85 00:03:42,320 --> 00:03:45,200 But really it's just one error that sort of cascades and creates 86 00:03:45,200 --> 00:03:47,990 another one because it doesn't understand what's happening before. 87 00:03:47,990 --> 00:03:50,150 And if you can fix that one error at the beginning, 88 00:03:50,150 --> 00:03:55,065 it might resolve one or more, or all, of the remaining errors. 89 00:03:55,065 --> 00:03:56,440 So I'll clear my terminal window. 90 00:03:56,440 --> 00:03:57,560 And we'll try this again. 91 00:03:57,560 --> 00:03:59,800 But we'll preface this by saying help50 first. 92 00:03:59,800 --> 00:04:03,370 So help50 make example2. 93 00:04:03,370 --> 00:04:04,780 Let's see. 94 00:04:04,780 --> 00:04:06,910 Use of undeclared identifier string. 95 00:04:06,910 --> 00:04:08,500 Did you mean standard in? 96 00:04:08,500 --> 00:04:09,890 Well, I'm assuming probably not. 97 00:04:09,890 --> 00:04:12,100 Let's take a look at my code. 98 00:04:12,100 --> 00:04:12,600 No. 99 00:04:12,600 --> 00:04:15,540 I meant to use string there on line five. 100 00:04:15,540 --> 00:04:18,630 So by undeclared identifier, Clang means you've used a name string 101 00:04:18,630 --> 00:04:20,850 on line five which hasn't been defined. 102 00:04:20,850 --> 00:04:25,269 Did you forget to #include cs50.h in which string is defined atop your file? 103 00:04:25,269 --> 00:04:26,310 Well, here, again, I did. 104 00:04:26,310 --> 00:04:29,620 I did forget to include cs50.h this time. 105 00:04:29,620 --> 00:04:31,590 So it gave me another clue here. 106 00:04:31,590 --> 00:04:33,300 But I had seven errors. 107 00:04:33,300 --> 00:04:34,970 So hopefully this resolves most of them. 108 00:04:34,970 --> 00:04:36,450 Lets clear this and see if it does. 109 00:04:36,450 --> 00:04:39,011 We'll try and make example2 again. 110 00:04:39,011 --> 00:04:39,510 And it did. 111 00:04:39,510 --> 00:04:42,450 So even though it said I had seven errors, I really didn't. 112 00:04:42,450 --> 00:04:44,100 I just had the one. 113 00:04:44,100 --> 00:04:46,980 And because that one kind of threw everything else off, 114 00:04:46,980 --> 00:04:51,120 it just kind of cascaded down and really messed us up. 115 00:04:51,120 --> 00:04:51,782 All right. 116 00:04:51,782 --> 00:04:53,240 Let's take a look at example three. 117 00:04:53,240 --> 00:04:55,830 We'll try and make example three. 118 00:04:55,830 --> 00:04:56,940 Seven errors again. 119 00:04:56,940 --> 00:04:57,830 Ugh, man. 120 00:04:57,830 --> 00:05:00,720 Let's see what I got here. 121 00:05:00,720 --> 00:05:04,460 Looks like I have a for loop that's going from 1 to 10. 122 00:05:04,460 --> 00:05:07,800 And it's supposed to print out a new integer on each line. 123 00:05:07,800 --> 00:05:10,410 That looks OK to me, at least at first glance. 124 00:05:10,410 --> 00:05:12,554 I don't really know what the issue could be here. 125 00:05:12,554 --> 00:05:14,470 But help50 might be able to help us out again. 126 00:05:14,470 --> 00:05:16,860 So we'll try one more time help50 make example3. 127 00:05:16,860 --> 00:05:19,380 And, again, you'll see that help50 is commonly 128 00:05:19,380 --> 00:05:22,310 going to be used most of the time-- although it's not all it can do. 129 00:05:22,310 --> 00:05:24,920 And we'll take a look at a couple of examples of that in a second. 130 00:05:24,920 --> 00:05:27,330 You're going to use help50 most of the time when there are compile time 131 00:05:27,330 --> 00:05:29,496 errors that prevent your program from being compiled 132 00:05:29,496 --> 00:05:31,240 and have to be resolved first. 133 00:05:31,240 --> 00:05:33,234 So we'll try and help50 this one. 134 00:05:33,234 --> 00:05:35,400 Looks like it says on line five it looks like you're 135 00:05:35,400 --> 00:05:38,910 trying to declare a variable that's already been declared elsewhere. 136 00:05:38,910 --> 00:05:40,000 I don't see that. 137 00:05:40,000 --> 00:05:41,220 But then it tells me a little bit more. 138 00:05:41,220 --> 00:05:44,095 If you meant to create a for loop be sure that each part is separated 139 00:05:44,095 --> 00:05:46,080 with a semicolon rather than a comma. 140 00:05:46,080 --> 00:05:50,040 So here I've got commas, and I'm supposed to have semicolons. 141 00:05:50,040 --> 00:05:53,640 So it's, again, little things like this where it's little syntax things where 142 00:05:53,640 --> 00:05:55,757 if you were able to get in touch with somebody 143 00:05:55,757 --> 00:05:58,590 you could just kind of look at your code really quickly and be like, 144 00:05:58,590 --> 00:06:01,710 oh, well, you really just need to put in a semicolon here instead of a comma. 145 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 146 00:06:05,043 --> 00:06:08,940 waiting for somebody to give you that sort of shining moment right 147 00:06:08,940 --> 00:06:11,610 where suddenly the error is revealed. 148 00:06:11,610 --> 00:06:14,580 You can use help50 to try and help you along and accelerate this 149 00:06:14,580 --> 00:06:17,580 so that you don't get stuck waiting, and you can get a little resolution 150 00:06:17,580 --> 00:06:20,262 for your errors a little more quickly. 151 00:06:20,262 --> 00:06:22,720 Of course, we'll just confirm with trying to make it again. 152 00:06:22,720 --> 00:06:24,060 And it compiled no problem. 153 00:06:24,060 --> 00:06:25,572 I could run this program. 154 00:06:25,572 --> 00:06:28,530 And it will print out the numbers 1 through 10, each on separate lines. 155 00:06:28,530 --> 00:06:31,488 We can't see them all here because my terminal window is not big enough 156 00:06:31,488 --> 00:06:33,760 to hold them, but they're all there. 157 00:06:33,760 --> 00:06:34,260 All right. 158 00:06:34,260 --> 00:06:35,700 I got one more example here. 159 00:06:35,700 --> 00:06:40,890 And then I'll show you two examples of using help50 not in the make context 160 00:06:40,890 --> 00:06:46,400 necessarily, or in the Clang context. 161 00:06:46,400 --> 00:06:50,530 So let's try and make example4. 162 00:06:50,530 --> 00:06:51,400 I have one error. 163 00:06:51,400 --> 00:06:54,450 "Expression result unused, n times 5." 164 00:06:54,450 --> 00:06:56,270 Not really sure what that means. 165 00:06:56,270 --> 00:06:58,949 So let's just quickly pop open example4 here at the top. 166 00:06:58,949 --> 00:07:01,240 Looks like what I want to do is have this print out 50. 167 00:07:01,240 --> 00:07:02,323 So I set n as equal to 10. 168 00:07:02,323 --> 00:07:03,970 I multiply n by 5 to get 50. 169 00:07:03,970 --> 00:07:06,160 And I want to print out 50. 170 00:07:06,160 --> 00:07:07,870 So I wonder what the issue could be. 171 00:07:07,870 --> 00:07:11,644 So let's help50 make example4. 172 00:07:11,644 --> 00:07:15,650 On line six of example 4.c you are performing an operation, 173 00:07:15,650 --> 00:07:18,350 but not saving the result. Did you mean to print or store 174 00:07:18,350 --> 00:07:19,460 the result in a variable? 175 00:07:19,460 --> 00:07:22,155 So remember, when we are doing mathematical manipulations 176 00:07:22,155 --> 00:07:24,780 to variables, we always have to assign the result to something. 177 00:07:24,780 --> 00:07:29,000 And here what I probably meant to say is either n equals n times 5, 178 00:07:29,000 --> 00:07:33,050 to change n from 10 into 50, or the more shorthand version, 179 00:07:33,050 --> 00:07:36,870 n times equals 5, which would also work just fine. 180 00:07:36,870 --> 00:07:37,900 So I can save this. 181 00:07:37,900 --> 00:07:38,900 Hopefully this fixes it. 182 00:07:38,900 --> 00:07:41,380 I'll try and recompile it. 183 00:07:41,380 --> 00:07:45,500 And I'll try and run it to see if I get 50 printed out. 184 00:07:45,500 --> 00:07:47,420 So that's a couple of uses of, in particular 185 00:07:47,420 --> 00:07:49,160 this is help50 helping with Clang. 186 00:07:49,160 --> 00:07:52,250 Although every time we were doing this we were typing make. 187 00:07:52,250 --> 00:07:55,570 Remember that make is actually just a wrapper 188 00:07:55,570 --> 00:07:58,220 for Clang, which is the name of the actual compiler 189 00:07:58,220 --> 00:08:00,262 that we're using in CS50 IDE. 190 00:08:00,262 --> 00:08:01,970 What happens though if I try and do this? 191 00:08:01,970 --> 00:08:04,310 There's no file called example5. 192 00:08:04,310 --> 00:08:06,191 So make example5. 193 00:08:06,191 --> 00:08:07,940 Unlike the previous four, this is actually 194 00:08:07,940 --> 00:08:09,950 going to be a help50 that helps with a message 195 00:08:09,950 --> 00:08:13,351 from make as opposed to a message from Clang. 196 00:08:13,351 --> 00:08:14,600 Now, obviously it's not there. 197 00:08:14,600 --> 00:08:16,475 So you can probably figure out what it means. 198 00:08:16,475 --> 00:08:19,990 But in case you didn't, I could preface it with help50. 199 00:08:19,990 --> 00:08:24,060 "Do you actually have a file called example5.c in the current directory?" 200 00:08:24,060 --> 00:08:25,310 Well, I don't. 201 00:08:25,310 --> 00:08:28,350 So I'm trying to compile a program that doesn't exist. 202 00:08:28,350 --> 00:08:30,530 So this is just help50, again, giving me a clue, 203 00:08:30,530 --> 00:08:33,179 like, well, maybe you're making a little bit of a mistake here. 204 00:08:33,179 --> 00:08:33,762 And it's true. 205 00:08:33,762 --> 00:08:35,480 I am making a bit of a mistake. 206 00:08:35,480 --> 00:08:36,809 One more example here. 207 00:08:36,809 --> 00:08:39,600 Let's say that I want to change directories into another directory. 208 00:08:39,600 --> 00:08:42,870 So I want to ls example6. 209 00:08:42,870 --> 00:08:44,810 There is, again, no example6 here. 210 00:08:44,810 --> 00:08:48,050 "ls cannot access example6, no such file or directory." 211 00:08:48,050 --> 00:08:50,180 Again, help50 might be able to help with this. 212 00:08:50,180 --> 00:08:52,446 So I'll preface it one more time. 213 00:08:52,446 --> 00:08:53,810 Are you sure example6 exists? 214 00:08:53,810 --> 00:08:55,370 Did you misspell example6? 215 00:08:55,370 --> 00:08:56,250 It doesn't exist. 216 00:08:56,250 --> 00:08:58,630 Maybe I had typed it wrong and I thought it was working. 217 00:08:58,630 --> 00:08:59,630 So it's just a reminder. 218 00:08:59,630 --> 00:09:00,791 Did you check that? 219 00:09:00,791 --> 00:09:02,040 Oh, maybe I had misspelled it. 220 00:09:02,040 --> 00:09:04,665 Maybe I meant to do something else, and then I can take a look. 221 00:09:04,665 --> 00:09:07,910 Now, help50 is a tool that is still in development. 222 00:09:07,910 --> 00:09:10,050 We actually have an open source GitHub repository. 223 00:09:10,050 --> 00:09:13,216 So as you go through the class and you become more comfortable, particularly 224 00:09:13,216 --> 00:09:16,700 as you start to learn Python, which is the tool that help50 is written in, 225 00:09:16,700 --> 00:09:20,540 you can actually head to CS50's public GitHub repositories and take a look 226 00:09:20,540 --> 00:09:22,640 and see what types of error messages that 227 00:09:22,640 --> 00:09:25,700 are a little more arcane that we're trying to catch and have help50 228 00:09:25,700 --> 00:09:28,070 explain in more human understandable terms 229 00:09:28,070 --> 00:09:30,666 so that if you want to contribute to that you actually can. 230 00:09:30,666 --> 00:09:32,540 And if you encounter an error that you're not 231 00:09:32,540 --> 00:09:37,280 getting, that help50 doesn't understand, and you want to report that error 232 00:09:37,280 --> 00:09:40,100 and hope that somebody else maybe can help match it, 233 00:09:40,100 --> 00:09:42,017 you can do that through that platform as well. 234 00:09:42,017 --> 00:09:43,808 So this is definitely a collaborative tool. 235 00:09:43,808 --> 00:09:46,700 And we welcome you to continue to contribute either solutions as you 236 00:09:46,700 --> 00:09:49,640 become more comfortable, or issues that we can try and resolve 237 00:09:49,640 --> 00:09:52,680 to make it a more robust tool. 238 00:09:52,680 --> 00:09:53,180 All right. 239 00:09:53,180 --> 00:09:55,740 So another tool that we have is one called eprintf. 240 00:09:55,740 --> 00:10:00,650 Now, it's really common when you are starting to debug your programs to kind 241 00:10:00,650 --> 00:10:03,230 of pepper them with printf statements. 242 00:10:03,230 --> 00:10:05,634 It's sort of like a sanity check where you're checking, 243 00:10:05,634 --> 00:10:06,800 OK, well, this line printed. 244 00:10:06,800 --> 00:10:08,710 And then I have some lines of code that run. 245 00:10:08,710 --> 00:10:09,650 And then this line printed. 246 00:10:09,650 --> 00:10:12,275 Like you're trying to figure out where things are going wrong. 247 00:10:12,275 --> 00:10:15,170 The trouble with printf is it doesn't necessarily tell you 248 00:10:15,170 --> 00:10:18,036 where the program is going wrong. 249 00:10:18,036 --> 00:10:20,660 You have to kind of go back and scroll through your source code 250 00:10:20,660 --> 00:10:23,160 to figure out which error message corresponds to that. 251 00:10:23,160 --> 00:10:24,590 That's not always that helpful. 252 00:10:24,590 --> 00:10:25,837 It's not a huge deal. 253 00:10:25,837 --> 00:10:28,170 But we have this tool that makes it a little bit easier. 254 00:10:28,170 --> 00:10:30,597 So it's called eprintf, which stands for error printf. 255 00:10:30,597 --> 00:10:32,930 And I'm just going to navigate into my eprintf directory 256 00:10:32,930 --> 00:10:35,120 where I have just one example file. 257 00:10:35,120 --> 00:10:38,490 I'm going to open that up here and show you what it does. 258 00:10:38,490 --> 00:10:39,759 So not much to this. 259 00:10:39,759 --> 00:10:40,925 I'm going to scroll up here. 260 00:10:40,925 --> 00:10:44,570 Basically what I'm doing is I'm asking the user to give me an integer. 261 00:10:44,570 --> 00:10:47,090 And then I actually get that integer from them. 262 00:10:47,090 --> 00:10:49,340 And then I have eprintf, integer obtained. 263 00:10:49,340 --> 00:10:50,840 Now, this means nothing to the user. 264 00:10:50,840 --> 00:10:53,540 It's an error message to make sure for me, 265 00:10:53,540 --> 00:10:56,870 as the person who's testing this program, that I got to this point 266 00:10:56,870 --> 00:10:58,142 in the program. 267 00:10:58,142 --> 00:11:00,350 And we'll see exactly what eprintf does that gives it 268 00:11:00,350 --> 00:11:02,474 a little bit of a leg up over printf, which is just 269 00:11:02,474 --> 00:11:03,860 going to display to the terminal. 270 00:11:03,860 --> 00:11:04,980 Then I'm doing a couple of different things. 271 00:11:04,980 --> 00:11:06,910 If x is less than 0, I'm going to print x is negative. 272 00:11:06,910 --> 00:11:08,951 If it's greater than zero, I print x is positive. 273 00:11:08,951 --> 00:11:10,347 Otherwise I print x is 0. 274 00:11:10,347 --> 00:11:12,680 And then I have one more eprintf call at the bottom here 275 00:11:12,680 --> 00:11:14,360 which is got through the program. 276 00:11:14,360 --> 00:11:17,720 So if I see that eprintf, that means that I've succeeded 277 00:11:17,720 --> 00:11:21,870 and I've gotten through every single line of the program without crashing. 278 00:11:21,870 --> 00:11:26,410 So let's just quickly compile this with make eprintf. 279 00:11:26,410 --> 00:11:29,410 And we'll try and run ./eprintf. 280 00:11:29,410 --> 00:11:30,730 Please give me an integer. 281 00:11:30,730 --> 00:11:33,390 Let's give it 50. 282 00:11:33,390 --> 00:11:35,080 And look at the little difference here. 283 00:11:35,080 --> 00:11:42,430 So instead of just printing out what I said, it tells me where it came from. 284 00:11:42,430 --> 00:11:45,256 So it tells me what line it came from and what file it came from. 285 00:11:45,256 --> 00:11:47,880 As we write more and more complex programs later in the course, 286 00:11:47,880 --> 00:11:50,430 we might write programs that span multiple .c files. 287 00:11:50,430 --> 00:11:52,380 We might have eprintfs throughout them. 288 00:11:52,380 --> 00:11:56,550 So it's just a useful way to figure out exactly from where in your program, 289 00:11:56,550 --> 00:12:00,090 or as things are going through, where in your program 290 00:12:00,090 --> 00:12:03,060 the error message that you're seeing, or sort of the printf 291 00:12:03,060 --> 00:12:05,541 prompt that you're seeing comes from. 292 00:12:05,541 --> 00:12:08,040 So it's definitely a good tool to familiarize yourself with, 293 00:12:08,040 --> 00:12:09,831 particularly earlier on where you might not 294 00:12:09,831 --> 00:12:12,075 need the more complex tools of a debugger, which 295 00:12:12,075 --> 00:12:13,260 we're going to talk about in a second. 296 00:12:13,260 --> 00:12:14,670 But you just want to get sort of a sanity check 297 00:12:14,670 --> 00:12:17,220 to make sure that things are working the way you expect them to. 298 00:12:17,220 --> 00:12:17,720 OK. 299 00:12:17,720 --> 00:12:20,790 And the third and final tool that we're going to cover in this video 300 00:12:20,790 --> 00:12:21,870 is debug50. 301 00:12:21,870 --> 00:12:25,920 Now, debug50 is a GUI or Graphical User Interface 302 00:12:25,920 --> 00:12:33,450 wrapper for a tool known as GDB, which is a very richly developed debugging 303 00:12:33,450 --> 00:12:34,380 platform. 304 00:12:34,380 --> 00:12:37,200 And it will really help you take a look underneath the hood, 305 00:12:37,200 --> 00:12:39,120 inspect what is going on in your program, 306 00:12:39,120 --> 00:12:42,510 and try and figure out where things might be going wrong. 307 00:12:42,510 --> 00:12:45,440 In this example we're going to cover three different buggy videos. 308 00:12:45,440 --> 00:12:47,565 And I'm going to show you how to use debug50 309 00:12:47,565 --> 00:12:50,190 to sort of give you some clues as to what you might need to do. 310 00:12:50,190 --> 00:12:54,210 So the first thing I'm going to do here is navigate into my debug50 directory 311 00:12:54,210 --> 00:12:58,670 where I have three source files and three programs that are previously 312 00:12:58,670 --> 00:12:59,170 compiled. 313 00:12:59,170 --> 00:13:00,690 So these have compiled. 314 00:13:00,690 --> 00:13:02,910 I don't need help50 to tell me what's going on here 315 00:13:02,910 --> 00:13:06,300 because I've already got the compiled binaries here. 316 00:13:06,300 --> 00:13:08,820 But there's something going wrong in these programs that 317 00:13:08,820 --> 00:13:10,230 is not what I expect. 318 00:13:10,230 --> 00:13:13,920 So the first thing I want to do is run debug1's program, 319 00:13:13,920 --> 00:13:16,470 and then we'll take a look at debug1's source code. 320 00:13:16,470 --> 00:13:18,744 And then we'll take a look at how debug50 321 00:13:18,744 --> 00:13:20,910 can give us a little bit more information about what 322 00:13:20,910 --> 00:13:22,506 might be going wrong here. 323 00:13:22,506 --> 00:13:23,880 So here's what we're going to do. 324 00:13:23,880 --> 00:13:26,671 We're going to go, and I'm going to clear my terminal really quick, 325 00:13:26,671 --> 00:13:31,050 and we're going to run debug1's binary. 326 00:13:31,050 --> 00:13:32,200 Provide a number. 327 00:13:32,200 --> 00:13:32,700 OK. 328 00:13:32,700 --> 00:13:34,590 I'll provide one. 329 00:13:34,590 --> 00:13:35,840 You gave a one. 330 00:13:35,840 --> 00:13:36,590 Seems pretty good. 331 00:13:36,590 --> 00:13:37,482 Let's try this again. 332 00:13:37,482 --> 00:13:38,190 Provide a number. 333 00:13:38,190 --> 00:13:40,110 I'll give it two. 334 00:13:40,110 --> 00:13:41,140 You gave a one. 335 00:13:41,140 --> 00:13:42,831 That's not right. 336 00:13:42,831 --> 00:13:43,330 Zero? 337 00:13:43,330 --> 00:13:44,470 You gave a one. 338 00:13:44,470 --> 00:13:48,120 So it's always saying, I gave a one. 339 00:13:48,120 --> 00:13:48,620 I did. 340 00:13:48,620 --> 00:13:49,560 I gave a one the first time. 341 00:13:49,560 --> 00:13:51,684 So let's maybe take a look at what's going on here. 342 00:13:51,684 --> 00:13:54,510 So I have my program. 343 00:13:54,510 --> 00:13:56,500 I'm providing a number. 344 00:13:56,500 --> 00:13:57,000 OK. 345 00:13:57,000 --> 00:13:57,660 That works. 346 00:13:57,660 --> 00:13:59,185 If x is one, say you gave a one. 347 00:13:59,185 --> 00:14:01,060 Otherwise, apparently I'm not doing anything. 348 00:14:01,060 --> 00:14:05,536 It's not supposed to print anything if I didn't give it a one. 349 00:14:05,536 --> 00:14:06,730 So that's weird. 350 00:14:06,730 --> 00:14:08,977 So at this point if you're familiar with the code 351 00:14:08,977 --> 00:14:10,560 you might see where the issue is here. 352 00:14:10,560 --> 00:14:12,200 But let's pretend that we don't. 353 00:14:12,200 --> 00:14:13,200 Or maybe you don't. 354 00:14:13,200 --> 00:14:16,130 And that's totally OK as well. 355 00:14:16,130 --> 00:14:19,850 This debug50 tool can hopefully give a little bit more information 356 00:14:19,850 --> 00:14:22,000 and we can see what's happening. 357 00:14:22,000 --> 00:14:23,824 So what I want to do is the first thing you 358 00:14:23,824 --> 00:14:25,740 need to do when you're working with a debugger 359 00:14:25,740 --> 00:14:27,825 like GDB is to provide a breakpoint. 360 00:14:27,825 --> 00:14:30,870 What a breakpoint is is basically your program 361 00:14:30,870 --> 00:14:33,810 will execute until it hits that line of code. 362 00:14:33,810 --> 00:14:37,470 And then it will stop, or break, and wait for something to happen. 363 00:14:37,470 --> 00:14:39,900 If you don't know where to break in your code, 364 00:14:39,900 --> 00:14:43,080 because you don't even know where the issue might be happening, 365 00:14:43,080 --> 00:14:45,192 it's totally reasonable to break at main. 366 00:14:45,192 --> 00:14:48,150 The way that you set a breakpoint is right here to the left of the line 367 00:14:48,150 --> 00:14:51,090 numbers you'll notice that my cursor turned into a little like pointer 368 00:14:51,090 --> 00:14:52,090 finger there. 369 00:14:52,090 --> 00:14:56,316 If you click once, you get this sort of red light, or a stop light. 370 00:14:56,316 --> 00:14:58,940 That's basically your indicator that you have set a breakpoint. 371 00:14:58,940 --> 00:15:04,230 So my program will compile, and it will run until it gets to line six. 372 00:15:04,230 --> 00:15:06,510 At which point it's going to kind of freeze. 373 00:15:06,510 --> 00:15:09,570 And from there I can make very slow steps through my program. 374 00:15:09,570 --> 00:15:12,300 Usually when we're running our program it's like you compile it, 375 00:15:12,300 --> 00:15:13,710 and it's done. 376 00:15:13,710 --> 00:15:15,942 Here we can really force it to slow down, and look 377 00:15:15,942 --> 00:15:18,150 what it's doing line, by line, by line, and see if we 378 00:15:18,150 --> 00:15:21,089 can see where the issue might lie. 379 00:15:21,089 --> 00:15:22,130 So I've set a breakpoint. 380 00:15:22,130 --> 00:15:24,240 Now I need to run debug50. 381 00:15:24,240 --> 00:15:29,150 debug50 ./debug1. 382 00:15:29,150 --> 00:15:32,270 Cause that's the name of the program that I wanted to test. 383 00:15:32,270 --> 00:15:34,110 Hit Enter. 384 00:15:34,110 --> 00:15:36,797 And if you've watched our CS50 IDE tutorial introduction video 385 00:15:36,797 --> 00:15:38,630 you noticed I talked about the debugger tab. 386 00:15:38,630 --> 00:15:41,940 You'll notice the debugger tab on the right has popped open. 387 00:15:41,940 --> 00:15:43,940 And I'm giving a little bit of information here. 388 00:15:43,940 --> 00:15:45,869 I have information about the call stacks. 389 00:15:45,869 --> 00:15:47,660 So if I had multiple functions being called 390 00:15:47,660 --> 00:15:49,785 it would tell me which function I'm in at the time, 391 00:15:49,785 --> 00:15:52,460 and which functions are waiting for stuff to happen. 392 00:15:52,460 --> 00:15:54,430 Local variables in my program. 393 00:15:54,430 --> 00:15:55,340 There are values. 394 00:15:55,340 --> 00:15:57,290 What type they are, and so on. 395 00:15:57,290 --> 00:16:00,430 Really useful stuff. 396 00:16:00,430 --> 00:16:02,110 And my program has frozen, right. 397 00:16:02,110 --> 00:16:04,902 It has not printed out "please provide a number." 398 00:16:04,902 --> 00:16:06,610 It's just waiting for me to do something. 399 00:16:06,610 --> 00:16:09,971 And the way I can control what my program does is up here at the top. 400 00:16:09,971 --> 00:16:12,970 I have resume, which is basically just going to speed through my program 401 00:16:12,970 --> 00:16:15,520 again, ignoring any more breakpoints. 402 00:16:15,520 --> 00:16:21,829 I have step over, which is going to move one line ahead. 403 00:16:21,829 --> 00:16:24,370 And generally you're going to want to step over any functions 404 00:16:24,370 --> 00:16:27,299 that you did not write, because if you step into them, which 405 00:16:27,299 --> 00:16:30,340 is the next example, it's actually going to go and look at printf's code, 406 00:16:30,340 --> 00:16:32,950 and start executing printf's code one line at a time. 407 00:16:32,950 --> 00:16:35,140 And we can probably assume that printf is OK. 408 00:16:35,140 --> 00:16:37,660 And we can probably assume that getint, for example, is OK. 409 00:16:37,660 --> 00:16:39,160 So we don't need to step into those. 410 00:16:39,160 --> 00:16:40,180 We can step over them. 411 00:16:40,180 --> 00:16:43,480 If you're going into a block, for example, like an if, or a function 412 00:16:43,480 --> 00:16:45,470 that you wrote, you might want to step into it, 413 00:16:45,470 --> 00:16:50,090 unless you happen to know for sure that it's not an issue in that function. 414 00:16:50,090 --> 00:16:53,030 So you can start to proceed through those a line at a time. 415 00:16:53,030 --> 00:16:54,537 And then, lastly, there's step out. 416 00:16:54,537 --> 00:16:55,870 We're not in anything right now. 417 00:16:55,870 --> 00:16:57,640 So we can't step out. 418 00:16:57,640 --> 00:16:59,667 But if you step into a function and you realize, 419 00:16:59,667 --> 00:17:02,000 oh, I really shouldn't have done this, you can step out, 420 00:17:02,000 --> 00:17:03,430 which will just proceed through the rest of the function, 421 00:17:03,430 --> 00:17:06,161 and then pick up again at the next logical spot. 422 00:17:06,161 --> 00:17:08,869 So what I want to do here is start to proceed one line at a time. 423 00:17:08,869 --> 00:17:10,828 So I want this to print out "provide a number." 424 00:17:10,828 --> 00:17:13,577 So I'm going to step over this line, which is going to execute it. 425 00:17:13,577 --> 00:17:15,800 You can see it at the terminal there at the bottom. 426 00:17:15,800 --> 00:17:17,849 Then it's prompting me to provide a number. 427 00:17:17,849 --> 00:17:19,740 So I'll give it a three. 428 00:17:19,740 --> 00:17:20,627 One seems to work. 429 00:17:20,627 --> 00:17:21,960 So I'm going to give it a three. 430 00:17:21,960 --> 00:17:23,849 And I'll hit Enter. 431 00:17:23,849 --> 00:17:27,420 And then I will again step over. 432 00:17:27,420 --> 00:17:30,000 If x equals one printf. 433 00:17:30,000 --> 00:17:31,260 You gave a one. 434 00:17:31,260 --> 00:17:33,570 So I kind of want to step into this. 435 00:17:33,570 --> 00:17:35,820 And in particular, notice what's going to happen here. 436 00:17:35,820 --> 00:17:38,490 Notice that right now it says my variable x 437 00:17:38,490 --> 00:17:41,040 has a value of three, which is what I expect. 438 00:17:41,040 --> 00:17:46,290 But as I step into this, the value of x has changed to one. 439 00:17:46,290 --> 00:17:47,880 It's no longer three. 440 00:17:47,880 --> 00:17:50,040 So this statement is now true. 441 00:17:50,040 --> 00:17:51,720 It says, well, x is one. 442 00:17:51,720 --> 00:17:53,580 So you gave a one. 443 00:17:53,580 --> 00:17:56,100 And if I step over, that is what it will do. 444 00:17:56,100 --> 00:17:56,950 You gave a one. 445 00:17:56,950 --> 00:18:02,040 And if I stop one more time, the program finishes executing. 446 00:18:02,040 --> 00:18:04,500 Did you happen to see what the error there was? 447 00:18:04,500 --> 00:18:06,270 It's a silly little syntax thing. 448 00:18:06,270 --> 00:18:09,210 But I used a single equal sign instead of a double equal sign. 449 00:18:09,210 --> 00:18:13,200 So what I really did here is I assigned x to be one. 450 00:18:13,200 --> 00:18:18,090 Regardless of what x was at this point, I said x is equal to one. 451 00:18:18,090 --> 00:18:22,470 I assigned x to one, when I really meant to do this. 452 00:18:22,470 --> 00:18:25,680 If x equals equals one. 453 00:18:25,680 --> 00:18:30,390 And now let's just save this program really quickly. 454 00:18:30,390 --> 00:18:33,270 And we'll recompile it, because we have to recompile 455 00:18:33,270 --> 00:18:35,625 a program if we want to rerun it. 456 00:18:35,625 --> 00:18:38,250 Use equals to turn this comparison into an equality assignment. 457 00:18:38,250 --> 00:18:39,920 Now, the reason that this works is because I had put 458 00:18:39,920 --> 00:18:41,503 this extra set of parentheses in here. 459 00:18:41,503 --> 00:18:43,920 Generally if you tried to do this it wouldn't work. 460 00:18:43,920 --> 00:18:46,044 But I had to force it for purposes of this example. 461 00:18:46,044 --> 00:18:48,151 So I had to get rid of those parentheses as well. 462 00:18:48,151 --> 00:18:50,150 We'll try one more time to compile this program. 463 00:18:50,150 --> 00:18:51,440 Now it compiled successfully. 464 00:18:51,440 --> 00:18:53,000 We'll clear our terminal window. 465 00:18:53,000 --> 00:18:54,920 And let's try and debug50 one more time, just 466 00:18:54,920 --> 00:18:59,210 to make sure that everything is working the way we expect. 467 00:18:59,210 --> 00:19:01,160 We still have our breakpoint set at line six. 468 00:19:01,160 --> 00:19:04,700 So it's still going to freeze at the first possible opportunity after that. 469 00:19:04,700 --> 00:19:06,890 I want to step over this to provide a number. 470 00:19:06,890 --> 00:19:10,010 I'll give it three again. 471 00:19:10,010 --> 00:19:11,020 Step over. 472 00:19:11,020 --> 00:19:12,020 x is now equal to three. 473 00:19:12,020 --> 00:19:13,790 You can see here on the right. 474 00:19:13,790 --> 00:19:15,585 Now, let's step into this. 475 00:19:18,190 --> 00:19:19,071 Can't step into it. 476 00:19:19,071 --> 00:19:19,570 Why? 477 00:19:19,570 --> 00:19:21,110 Because x is not one anymore. 478 00:19:21,110 --> 00:19:23,770 So that next line of code on line 13 there 479 00:19:23,770 --> 00:19:26,960 is not going to execute because the condition is no longer true. 480 00:19:26,960 --> 00:19:28,930 So before I was assigning x to be one. 481 00:19:28,930 --> 00:19:30,379 And that's why it would go in. 482 00:19:30,379 --> 00:19:32,920 And thanks to debug50 I was able to see, oh, wait, this three 483 00:19:32,920 --> 00:19:34,874 is unexpectedly changing into a one. 484 00:19:34,874 --> 00:19:37,040 Maybe there's something going on wrong in that area. 485 00:19:37,040 --> 00:19:40,720 So that's one way that debug50 was able to help isolate where in the program 486 00:19:40,720 --> 00:19:43,520 things were going awry. 487 00:19:43,520 --> 00:19:44,020 All right. 488 00:19:44,020 --> 00:19:46,150 So I'm going to hit Resume here just to end the program, 489 00:19:46,150 --> 00:19:47,540 have it finish doing its thing. 490 00:19:47,540 --> 00:19:50,090 Didn't print anything because we didn't have a one. 491 00:19:50,090 --> 00:19:52,660 And now let's take a look at program number two. 492 00:19:52,660 --> 00:19:55,640 So I'll clear my terminal. 493 00:19:55,640 --> 00:20:00,450 And let's try and execute the debug2 program. 494 00:20:00,450 --> 00:20:03,330 "What percentage grade did you get as a number?" 495 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%. 496 00:20:08,400 --> 00:20:09,520 My grade is an E. 497 00:20:09,520 --> 00:20:10,020 OK. 498 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. 499 00:20:13,590 --> 00:20:18,257 So that should hopefully be like a C. Eh, I got an E. 500 00:20:18,257 --> 00:20:18,840 Wait a minute. 501 00:20:18,840 --> 00:20:21,480 What if I got like an A, I got everything? 502 00:20:21,480 --> 00:20:22,195 E. 503 00:20:22,195 --> 00:20:24,820 Well, again, this isn't doing exactly what I expected it to do. 504 00:20:24,820 --> 00:20:26,310 So let's take a look at the source code. 505 00:20:26,310 --> 00:20:28,685 And then let's take a look at debug50 and see if maybe it 506 00:20:28,685 --> 00:20:30,219 can give us some clues here. 507 00:20:30,219 --> 00:20:32,010 So I'll open up the source code for debug2. 508 00:20:32,010 --> 00:20:33,650 And I'll just close this one here. 509 00:20:33,650 --> 00:20:36,460 And I'll also just clear the terminal screen one more time. 510 00:20:36,460 --> 00:20:36,960 All right. 511 00:20:36,960 --> 00:20:39,293 So what percentage of the grade did you get as a number? 512 00:20:39,293 --> 00:20:40,140 Get an integer. 513 00:20:40,140 --> 00:20:42,098 What's happening here on line eight is I'm just 514 00:20:42,098 --> 00:20:46,080 transforming whatever the user gave me into a multiple of 10, 515 00:20:46,080 --> 00:20:48,420 so that divided by 10 times 10, that's a trick that 516 00:20:48,420 --> 00:20:49,836 works because of integer division. 517 00:20:49,836 --> 00:20:52,050 But say the user gives me 93. 518 00:20:52,050 --> 00:20:54,970 93 divided by 10 is nine, not 9.3. 519 00:20:54,970 --> 00:20:56,310 Remember, its integer division. 520 00:20:56,310 --> 00:20:58,530 And then 9 times 10 is 90. 521 00:20:58,530 --> 00:21:03,060 So I'm just basically dropping off the ones place of every number 522 00:21:03,060 --> 00:21:06,040 here and just transforming it into a multiple of 10. 523 00:21:06,040 --> 00:21:08,285 And then I have a letter character for a grade. 524 00:21:08,285 --> 00:21:09,930 It will get stored there. 525 00:21:09,930 --> 00:21:11,779 And then I'm using a switch statement, which 526 00:21:11,779 --> 00:21:15,070 is one form of conditional statement, to look over the different possibilities. 527 00:21:15,070 --> 00:21:19,630 So if I have a 90 or a 100 after executing lines seven, eight, 528 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, 529 00:21:24,750 --> 00:21:26,730 depending on what my scores are. 530 00:21:26,730 --> 00:21:29,551 But it seems like every time I'm doing this I'm getting an E. 531 00:21:29,551 --> 00:21:31,800 And, again, if you're familiar with switch statements, 532 00:21:31,800 --> 00:21:33,790 you might see what the issue is here. 533 00:21:33,790 --> 00:21:35,550 And if you're not familiar with switch statements, that's OK. 534 00:21:35,550 --> 00:21:38,258 Because switch statements are a little bit strange the first time 535 00:21:38,258 --> 00:21:38,970 you use them. 536 00:21:38,970 --> 00:21:43,249 But debug50 can help us figure out what is happening here. 537 00:21:43,249 --> 00:21:46,290 So first thing we got to do, of course, is we got to set that breakpoint. 538 00:21:46,290 --> 00:21:49,020 So I got to figure out where I want to set it. 539 00:21:49,020 --> 00:21:51,900 Well, it looks like I might have already set it here at line 11. 540 00:21:51,900 --> 00:21:55,290 And that seems like a fair enough place to do it. 541 00:21:55,290 --> 00:21:58,360 So let's set our breakpoint there. 542 00:21:58,360 --> 00:22:01,500 So our program will not freeze and pop open for us 543 00:22:01,500 --> 00:22:04,840 until we get to that point in the code. 544 00:22:04,840 --> 00:22:09,440 So we'll use debug50 on the debug program number two. 545 00:22:12,009 --> 00:22:14,300 "What percentage of the grade did you get as a number?" 546 00:22:14,300 --> 00:22:17,290 So let's say I got 100. 547 00:22:17,290 --> 00:22:18,730 And now we're frozen. 548 00:22:18,730 --> 00:22:22,372 And notice over here, grade has been set to negative one. 549 00:22:22,372 --> 00:22:23,330 There's no value there. 550 00:22:23,330 --> 00:22:26,650 But that makes sense, cause we haven't assigned grade equals something yet. 551 00:22:26,650 --> 00:22:29,000 Percent is 100 and 10th is 100. 552 00:22:29,000 --> 00:22:30,670 So we have the value we're expecting. 553 00:22:30,670 --> 00:22:36,920 10th is 100, which means when we get to line 13, grade A should get triggered. 554 00:22:36,920 --> 00:22:42,224 So let's step in one line at a time. 555 00:22:42,224 --> 00:22:45,050 All right. 556 00:22:45,050 --> 00:22:51,310 So notice that my grade is A. And then it's B. 557 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, 558 00:22:59,140 --> 00:23:01,560 that's what now gets printed. 559 00:23:01,560 --> 00:23:03,470 And that's not what I expect. 560 00:23:03,470 --> 00:23:06,980 So it seems like by using debug50 to step slowly 561 00:23:06,980 --> 00:23:08,960 through my program, what was happening is 562 00:23:08,960 --> 00:23:12,680 I wasn't just triggering the one case that I wanted to hit. 563 00:23:12,680 --> 00:23:16,160 I seemed to be hitting all of the different cases. 564 00:23:16,160 --> 00:23:17,730 And the grade kept changing. 565 00:23:17,730 --> 00:23:19,146 It started out at the right thing. 566 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. 567 00:23:22,730 --> 00:23:25,910 And the reason for that, and again, we'll cover this on our video 568 00:23:25,910 --> 00:23:27,950 on conditionals if you haven't seen it already, 569 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. 570 00:23:33,140 --> 00:23:36,790 I only ever want one of these things to be true. 571 00:23:36,790 --> 00:23:39,080 Now, it's true that you might end up in a situation 572 00:23:39,080 --> 00:23:41,830 where you actually want the behavior of falling through the cases, 573 00:23:41,830 --> 00:23:43,100 as it's known. 574 00:23:43,100 --> 00:23:44,570 But that's not what I want here. 575 00:23:44,570 --> 00:23:47,630 I want explicitly to be assigned one value. 576 00:23:47,630 --> 00:23:50,220 And then I don't want to look at the rest of the options. 577 00:23:50,220 --> 00:23:52,094 So what happened here is I just fell through. 578 00:23:52,094 --> 00:23:54,694 I kept executing every line of code from case 100 down. 579 00:23:54,694 --> 00:23:57,360 If I had started out at 80, it would have given me a B, and then 580 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, 581 00:24:00,200 --> 00:24:03,205 it would have given me a D and then an E. 582 00:24:03,205 --> 00:24:04,080 So I don't want that. 583 00:24:04,080 --> 00:24:08,790 So I have to include break statements at the end of all of my different options 584 00:24:08,790 --> 00:24:09,970 within the switch. 585 00:24:09,970 --> 00:24:15,240 And if I save this and I recompile it, and I clear my terminal 586 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. 587 00:24:20,470 --> 00:24:21,030 That's good. 588 00:24:21,030 --> 00:24:24,050 If I get an 80, I have a B, and so on. 589 00:24:24,050 --> 00:24:26,950 And so, again, by using the tools this time 590 00:24:26,950 --> 00:24:30,614 of seeing that I was hitting all of these different lines of code, 591 00:24:30,614 --> 00:24:32,530 not necessarily that variables were changing-- 592 00:24:32,530 --> 00:24:34,821 although it was useful to see that A was turning into B 593 00:24:34,821 --> 00:24:38,290 and turning into C. What was more useful for me there anyway was seeing 594 00:24:38,290 --> 00:24:40,522 that I was hitting all of these lines of code 595 00:24:40,522 --> 00:24:41,980 that I shouldn't have been hitting. 596 00:24:41,980 --> 00:24:44,104 I should have only been hitting the very one, which 597 00:24:44,104 --> 00:24:46,420 was case 90, colon, case 100 colon. 598 00:24:46,420 --> 00:24:50,110 Because that was what I had typed in, a 90 or a 100. 599 00:24:50,110 --> 00:24:52,932 So it was strange that I ended up falling through. 600 00:24:52,932 --> 00:24:54,640 And being able to see it go line by line, 601 00:24:54,640 --> 00:24:58,750 as opposed to just the program running so quickly because it's so short, 602 00:24:58,750 --> 00:25:00,029 that was a good clue for me. 603 00:25:00,029 --> 00:25:01,320 We have one more buggy program. 604 00:25:01,320 --> 00:25:03,653 And let's take a look at that one and see if debug50 can 605 00:25:03,653 --> 00:25:06,330 help us figure that one out as well. 606 00:25:06,330 --> 00:25:09,480 So I'll close this code window here. 607 00:25:09,480 --> 00:25:11,880 And let's run debug3. 608 00:25:11,880 --> 00:25:13,940 How many stars? 609 00:25:13,940 --> 00:25:15,150 Five. 610 00:25:15,150 --> 00:25:16,290 Give me six. 611 00:25:16,290 --> 00:25:17,550 How many stars? 612 00:25:17,550 --> 00:25:18,922 Zero. 613 00:25:18,922 --> 00:25:20,810 it gives me one. 614 00:25:20,810 --> 00:25:21,960 How many stars? 615 00:25:21,960 --> 00:25:23,450 40. 616 00:25:23,450 --> 00:25:26,860 Well, I'm not going to count that, but it's 41 is what it is. 617 00:25:26,860 --> 00:25:28,990 So I'm getting a few too many stars. 618 00:25:28,990 --> 00:25:32,980 But if I look at my debug3 source code, I'm going from zero to x, 619 00:25:32,980 --> 00:25:35,860 and I'm printing out a star for every time. 620 00:25:35,860 --> 00:25:39,020 So it seems like that should be working just fine, but it's not. 621 00:25:39,020 --> 00:25:43,780 So maybe the debugger can help us figure this out a little bit more cleanly. 622 00:25:43,780 --> 00:25:44,710 So let's pop it open. 623 00:25:44,710 --> 00:25:46,690 Let's first set a breakpoint. 624 00:25:46,690 --> 00:25:50,277 It seems like the integer part is maybe not working. 625 00:25:50,277 --> 00:25:52,360 So instead of setting it to breakpoint after that, 626 00:25:52,360 --> 00:25:55,420 maybe it somehow is turning five into six? 627 00:25:55,420 --> 00:25:55,979 I don't know. 628 00:25:55,979 --> 00:25:57,520 Let's set our breakpoint before that. 629 00:25:57,520 --> 00:25:59,170 Let's just set our breakpoint right at main. 630 00:25:59,170 --> 00:26:00,490 And there was a breakpoint here. 631 00:26:00,490 --> 00:26:01,531 We'll just get rid of it. 632 00:26:01,531 --> 00:26:04,252 You can double click on a breakpoint to make it go away if you 633 00:26:04,252 --> 00:26:05,710 don't want to use that one anymore. 634 00:26:05,710 --> 00:26:06,940 And you can also set multiple breakpoints. 635 00:26:06,940 --> 00:26:08,660 We're not doing it in these examples. 636 00:26:08,660 --> 00:26:10,630 But I could set a breakpoint at first spot, 637 00:26:10,630 --> 00:26:12,820 and then maybe another one a little bit later on. 638 00:26:12,820 --> 00:26:15,440 It would stop at that point as well. 639 00:26:15,440 --> 00:26:15,940 All right. 640 00:26:15,940 --> 00:26:17,470 So let's try and compile this. 641 00:26:17,470 --> 00:26:19,630 So really quickly recompile. 642 00:26:19,630 --> 00:26:24,060 And then we'll run debug50 to take a look 643 00:26:24,060 --> 00:26:25,560 at what's happening in this program. 644 00:26:29,720 --> 00:26:30,765 All right. 645 00:26:30,765 --> 00:26:31,390 How many stars? 646 00:26:31,390 --> 00:26:32,556 So, again, we broke at main. 647 00:26:32,556 --> 00:26:34,770 So it's going to freeze at line six and wait. 648 00:26:34,770 --> 00:26:38,130 If I step over this line, it will print out how many stars. 649 00:26:38,130 --> 00:26:41,330 Let's say that I want five. 650 00:26:41,330 --> 00:26:43,560 Then we'll step over this. 651 00:26:43,560 --> 00:26:46,670 Because we don't need to step in to get in presumably. 652 00:26:46,670 --> 00:26:53,350 And when we get through, I's value is 32,677, which is actually OK. 653 00:26:53,350 --> 00:26:56,260 It hasn't been set yet, because line nine has not executed. 654 00:26:56,260 --> 00:26:57,670 But x is five. 655 00:26:57,670 --> 00:26:59,740 It didn't somehow transform into six. 656 00:26:59,740 --> 00:27:02,860 So what I now know at least is that my error somewhere 657 00:27:02,860 --> 00:27:04,450 happens from line nine down. 658 00:27:04,450 --> 00:27:05,310 It's not line six. 659 00:27:05,310 --> 00:27:06,430 It's not line seven. 660 00:27:06,430 --> 00:27:09,730 It's got to be after that, because x has the correct value. 661 00:27:09,730 --> 00:27:10,290 It has five. 662 00:27:10,290 --> 00:27:13,300 It didn't somehow get transformed into six. 663 00:27:13,300 --> 00:27:15,610 But I's value is 32,767. 664 00:27:15,610 --> 00:27:16,570 This is a red herring. 665 00:27:16,570 --> 00:27:17,320 This is not a bug. 666 00:27:17,320 --> 00:27:19,630 Like I said, line nine has not executed yet. 667 00:27:19,630 --> 00:27:23,430 Once line nine executes then I will be set at least to zero, 668 00:27:23,430 --> 00:27:24,520 as we'll see right now. 669 00:27:24,520 --> 00:27:26,030 So we'll step into this loop. 670 00:27:26,030 --> 00:27:28,510 Notice now I is zero, which is what we expect. 671 00:27:28,510 --> 00:27:29,890 Then it will print a star. 672 00:27:29,890 --> 00:27:32,806 I'm going to step over that, because I don't want to step into printf. 673 00:27:32,806 --> 00:27:34,170 So we'll step over. 674 00:27:34,170 --> 00:27:37,550 Notice that it printed one star to the terminal. 675 00:27:37,550 --> 00:27:38,640 Step again. 676 00:27:38,640 --> 00:27:40,204 I is now one. 677 00:27:40,204 --> 00:27:41,120 That's what we expect. 678 00:27:41,120 --> 00:27:43,250 We went through one iteration of the loop. 679 00:27:43,250 --> 00:27:44,935 I incremented by one. 680 00:27:44,935 --> 00:27:46,080 I'm going to step over. 681 00:27:46,080 --> 00:27:46,820 Print. 682 00:27:46,820 --> 00:27:49,020 OK. 683 00:27:49,020 --> 00:27:51,360 Two. 684 00:27:51,360 --> 00:27:53,650 Three. 685 00:27:53,650 --> 00:27:55,782 Four. 686 00:27:55,782 --> 00:27:57,740 Now, at this point I should be breaking, right. 687 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. 688 00:28:01,930 --> 00:28:02,430 Uh-oh. 689 00:28:02,430 --> 00:28:04,460 I see my bug now already, right. 690 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. 691 00:28:08,840 --> 00:28:13,400 So I saw it even before debug50 saw it for me. 692 00:28:13,400 --> 00:28:18,320 But it's true if I step into this loop, now I's value is five. 693 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. 694 00:28:22,152 --> 00:28:23,860 But it actually went into the loop, which 695 00:28:23,860 --> 00:28:27,670 means it's going to execute this line of code again. 696 00:28:27,670 --> 00:28:35,370 And now it's true that if I step into this, I goes away, right. 697 00:28:35,370 --> 00:28:39,530 Because if I became six, this loop would no longer run. 698 00:28:39,530 --> 00:28:40,464 So it goes away. 699 00:28:40,464 --> 00:28:41,630 And I break out of the loop. 700 00:28:41,630 --> 00:28:42,890 And I jump down to line 12. 701 00:28:42,890 --> 00:28:45,560 But I've printed out six stars instead of five. 702 00:28:45,560 --> 00:28:48,500 Now, again, these examples are a little bit contrived 703 00:28:48,500 --> 00:28:52,800 for the purposes of showing you how to use the debugger. 704 00:28:52,800 --> 00:28:56,540 It's not supposed to necessarily find the bug for you. 705 00:28:56,540 --> 00:29:00,260 But it's supposed to slow the computer down enough that you 706 00:29:00,260 --> 00:29:02,605 can see the steps that it's doing. 707 00:29:02,605 --> 00:29:06,260 So the values on the right, being able to track what values variables 708 00:29:06,260 --> 00:29:08,150 have is useful. 709 00:29:08,150 --> 00:29:12,950 Also I didn't show this, but you can actually change the value of variables 710 00:29:12,950 --> 00:29:13,450 if you want. 711 00:29:13,450 --> 00:29:15,434 I could say x is equal to 23. 712 00:29:15,434 --> 00:29:17,600 I could do this in the middle of my program running, 713 00:29:17,600 --> 00:29:19,670 between doing different lines to change things, 714 00:29:19,670 --> 00:29:21,860 to see if the behavior is affected in any way. 715 00:29:21,860 --> 00:29:23,390 It wouldn't have been that useful here because I've already 716 00:29:23,390 --> 00:29:24,349 broken out of the loop. 717 00:29:24,349 --> 00:29:27,139 But if I wanted to somehow make it artificially print more and more 718 00:29:27,139 --> 00:29:29,310 because I haven't figured it out yet, I can do that. 719 00:29:29,310 --> 00:29:31,770 You can do that with any local variable there as well. 720 00:29:31,770 --> 00:29:34,430 You can use this to inspect strings and arrays as well, 721 00:29:34,430 --> 00:29:35,840 which we're not going to get into here, because this is just 722 00:29:35,840 --> 00:29:37,970 supposed to be a general tutorial. 723 00:29:37,970 --> 00:29:41,180 But, again, the goal is not so much to be, here's the bug. 724 00:29:41,180 --> 00:29:47,330 It's to slow things down enough that you can see exactly what the computer is 725 00:29:47,330 --> 00:29:50,120 doing, and see if at any point it deviates 726 00:29:50,120 --> 00:29:52,160 from what you expect it to be doing. 727 00:29:52,160 --> 00:29:54,710 And that's what all these debugging tools are used for, 728 00:29:54,710 --> 00:29:57,230 particularly this GDB based one called debug50. 729 00:29:57,230 --> 00:29:58,050 But eprintf. 730 00:29:58,050 --> 00:30:00,800 Make sure that your program is printing out 731 00:30:00,800 --> 00:30:03,130 sort of sanity check messages in the right spot. 732 00:30:03,130 --> 00:30:06,710 help50 is supposed to give you some clues about where 733 00:30:06,710 --> 00:30:09,260 you might have compile time errors. 734 00:30:09,260 --> 00:30:12,050 And debug50 is supposed to help you figure out 735 00:30:12,050 --> 00:30:13,630 where your runtime errors are. 736 00:30:13,630 --> 00:30:15,671 So use all these tools in conjunction, and you'll 737 00:30:15,671 --> 00:30:18,402 be well on your way to debugging code like an expert in no time. 738 00:30:18,402 --> 00:30:19,490 I'm Doug Lloyd. 739 00:30:19,490 --> 00:30:21,300 This is CS50.