1 00:00:00,000 --> 00:00:00,309 2 00:00:00,309 --> 00:00:02,350 [? DAN ARMADARAS: ?] Hi, I'm [? Dan Armadaras ?]. 3 00:00:02,350 --> 00:00:04,410 Today, we're going to be looking at debugging. 4 00:00:04,410 --> 00:00:06,697 Not only are we going to talk about some techniques, 5 00:00:06,697 --> 00:00:09,280 but also we're going to look at some of the features contained 6 00:00:09,280 --> 00:00:14,170 within the CS50 IDE that allow you to easily debug a program. 7 00:00:14,170 --> 00:00:16,272 >> Just one example of something that can go wrong 8 00:00:16,272 --> 00:00:18,730 and it's actually something that we've already seen before. 9 00:00:18,730 --> 00:00:23,200 In this case, this is a C program that accepts an integer from the user, 10 00:00:23,200 --> 00:00:27,580 divides it by two, and provides the output back to the user. 11 00:00:27,580 --> 00:00:30,610 Now from what we've seen earlier in lectures, 12 00:00:30,610 --> 00:00:34,370 we know that this will actually cause specific types of division problems 13 00:00:34,370 --> 00:00:35,860 when we have odd numbers. 14 00:00:35,860 --> 00:00:40,330 >> Specifically, we'll just throw away anything after the decimal point. 15 00:00:40,330 --> 00:00:43,170 Now, we know that this happens to be the case. 16 00:00:43,170 --> 00:00:47,430 And if we run it, we can confirm our suspicions, first, by compiling. 17 00:00:47,430 --> 00:00:50,460 And then, by running and entering an odd number. 18 00:00:50,460 --> 00:00:51,720 >> This is nothing new. 19 00:00:51,720 --> 00:00:54,490 But this is actually an example of a bug that 20 00:00:54,490 --> 00:00:58,810 can exist within a larger program that becomes harder to track down. 21 00:00:58,810 --> 00:01:02,640 Even though we know what the issue is, the true crux of the matter 22 00:01:02,640 --> 00:01:06,250 might be trying to identify specifically where the error occurs, 23 00:01:06,250 --> 00:01:09,750 identifying what that problem is, and then fixing it. 24 00:01:09,750 --> 00:01:14,400 So provide this as an example of what might be something 25 00:01:14,400 --> 00:01:19,030 that we already know but can be buried within other elements of the code. 26 00:01:19,030 --> 00:01:23,090 >> So opening this other source code file as an example, 27 00:01:23,090 --> 00:01:27,165 this division problem is now part of a larger program. 28 00:01:27,165 --> 00:01:29,040 Still might be a little bit contrived, and we 29 00:01:29,040 --> 00:01:31,076 might be able to easily identify it, especially 30 00:01:31,076 --> 00:01:32,450 since we're just discussing this. 31 00:01:32,450 --> 00:01:38,250 But we can figure out that this problem can exist on a larger scale. 32 00:01:38,250 --> 00:01:45,450 >> If I compile this and now run it, enter an odd number, 33 00:01:45,450 --> 00:01:49,816 we can see that we don't get precisely the output that we may have expected. 34 00:01:49,816 --> 00:01:51,690 In this particular case, we might say that we 35 00:01:51,690 --> 00:01:56,060 want to count all of the numbers from one up to some specific number. 36 00:01:56,060 --> 00:01:58,130 And we can see that we have a variety of issues 37 00:01:58,130 --> 00:02:03,880 here if we're outputting, simply, 0 and 1 when we provide an input of 5. 38 00:02:03,880 --> 00:02:07,380 >> So we already know that there's a problem here. 39 00:02:07,380 --> 00:02:11,662 But we may not know precisely where this issue actually exists. 40 00:02:11,662 --> 00:02:13,620 Now one of the ways that we can try to fix this 41 00:02:13,620 --> 00:02:15,745 is something that we've already been introduced to. 42 00:02:15,745 --> 00:02:18,880 We can just use it on a larger scale. 43 00:02:18,880 --> 00:02:21,680 >> On line 14, we have this printf function, 44 00:02:21,680 --> 00:02:25,620 which allows us to print out the state of various pieces of information. 45 00:02:25,620 --> 00:02:28,880 And this is something that you should leverage within your program 46 00:02:28,880 --> 00:02:33,100 to try to figure out exactly what's happening in various lines of code. 47 00:02:33,100 --> 00:02:36,350 So even if this is not the final output that we actually 48 00:02:36,350 --> 00:02:39,830 want to produce out of this program, we still 49 00:02:39,830 --> 00:02:42,300 might have some debug statements where we 50 00:02:42,300 --> 00:02:46,970 can try to figure out precisely what is happening inside of our code. 51 00:02:46,970 --> 00:02:51,210 >> So in this case, I will printf with the debug tag. 52 00:02:51,210 --> 00:02:53,540 In this case, this is just a debug string 53 00:02:53,540 --> 00:02:56,840 that I'm up-putting so that it becomes very clear in the output of my code 54 00:02:56,840 --> 00:02:59,200 what it is that I want to show. 55 00:02:59,200 --> 00:03:04,410 And output here the number that we have computed. 56 00:03:04,410 --> 00:03:06,800 >> In this case, I might want to know precisely 57 00:03:06,800 --> 00:03:11,380 what is happening before and after some specific computation. 58 00:03:11,380 --> 00:03:16,224 So I might use a printf before and after that line of code. 59 00:03:16,224 --> 00:03:18,640 In this case, I could even make it a little bit more clear 60 00:03:18,640 --> 00:03:21,960 by saying debug before and debug after so 61 00:03:21,960 --> 00:03:26,540 that I don't confuse myself with multiple lines that look identical. 62 00:03:26,540 --> 00:03:32,290 >> Now if we recompile this and run it, enter a number like five again, 63 00:03:32,290 --> 00:03:35,090 we can see that we have now output before and after 64 00:03:35,090 --> 00:03:40,670 and find that we have not done a clear division or clear having of the number 65 00:03:40,670 --> 00:03:43,680 that we actually want to do. 66 00:03:43,680 --> 00:03:48,660 Now in this case, this is not really a clear output. 67 00:03:48,660 --> 00:03:52,440 It's not really a clear outcome that we want out of this particular program. 68 00:03:52,440 --> 00:03:54,427 >> And this is, again, a little bit contrived. 69 00:03:54,427 --> 00:03:57,510 But, perhaps, one of the things that we could do if the specification said 70 00:03:57,510 --> 00:04:01,900 that we want to divide this by 2 and add 1-- so in other words, 71 00:04:01,900 --> 00:04:04,550 we want to round up-- then we might know that we could 72 00:04:04,550 --> 00:04:08,060 do that particular thing, in this case. 73 00:04:08,060 --> 00:04:14,010 Now here we know that we will be able to add 1 to our halved number. 74 00:04:14,010 --> 00:04:16,490 >> Let's recompile this and confirm that this 75 00:04:16,490 --> 00:04:18,860 is behaving the way that we want to. 76 00:04:18,860 --> 00:04:21,980 We can see that now before having, we have the number 5. 77 00:04:21,980 --> 00:04:26,620 After having, we have the number 3, which according to our specification, 78 00:04:26,620 --> 00:04:29,292 is what we wanted to do. 79 00:04:29,292 --> 00:04:31,000 But if we look at the output here, we can 80 00:04:31,000 --> 00:04:33,760 see that we might have another bug altogether, which is 81 00:04:33,760 --> 00:04:36,940 that we are starting our count from 0. 82 00:04:36,940 --> 00:04:39,390 >> Now again, this is something that we have seen in the past 83 00:04:39,390 --> 00:04:42,500 and we can fix quite readily. 84 00:04:42,500 --> 00:04:44,790 But in this case, we also had the benefit 85 00:04:44,790 --> 00:04:48,940 of using the printf statement directly inside of the for loop 86 00:04:48,940 --> 00:04:52,930 to know precisely where that error was occurring. 87 00:04:52,930 --> 00:04:55,150 So printf statements are very useful in helping 88 00:04:55,150 --> 00:04:57,940 you determine where, precisely in your source code, 89 00:04:57,940 --> 00:05:00,620 a specific error is occurring. 90 00:05:00,620 --> 00:05:03,650 >> And it's also important to realize that, as we're writing code, 91 00:05:03,650 --> 00:05:06,052 we might have assumptions about the state of a program. 92 00:05:06,052 --> 00:05:08,510 Or we might have assumptions about what part of the program 93 00:05:08,510 --> 00:05:13,020 is actually correct or incorrect when later on as we build on that program 94 00:05:13,020 --> 00:05:15,950 and make it part of a complex and larger program 95 00:05:15,950 --> 00:05:19,700 that we realize that some aspect of that is actually buggy. 96 00:05:19,700 --> 00:05:22,680 >> Using printf can really help narrow down and identify 97 00:05:22,680 --> 00:05:26,430 the regions of a program that may not be behaving exactly the way that we 98 00:05:26,430 --> 00:05:29,500 expect, based on our assumptions. 99 00:05:29,500 --> 00:05:31,460 But there's other tools available, as well, 100 00:05:31,460 --> 00:05:34,860 that allow us to try to figure out where an error is occurring 101 00:05:34,860 --> 00:05:39,930 and also, specifically, what things are happening inside of the program. 102 00:05:39,930 --> 00:05:41,990 >> So using printf is very useful when we want 103 00:05:41,990 --> 00:05:45,900 to identify specific areas of a program that have some bug. 104 00:05:45,900 --> 00:05:47,730 But it also becomes tedious after a while. 105 00:05:47,730 --> 00:05:50,500 In this case, this is a relatively simple program 106 00:05:50,500 --> 00:05:52,750 with just one or two variables. 107 00:05:52,750 --> 00:05:57,260 And it becomes very easy for us to print out the value of those variables 108 00:05:57,260 --> 00:05:59,670 in the context of the larger program. 109 00:05:59,670 --> 00:06:02,670 >> But we might have a different program that has many variables. 110 00:06:02,670 --> 00:06:06,530 And it may not be quite so easy to use printf 111 00:06:06,530 --> 00:06:10,120 to try to evaluate what is happening to each one of those variables 112 00:06:10,120 --> 00:06:13,590 as the program is executing. 113 00:06:13,590 --> 00:06:16,960 There's a program that exists called a debugger program. 114 00:06:16,960 --> 00:06:20,320 In this case, the one that we will use is the GNU debugger, or GDB, 115 00:06:20,320 --> 00:06:24,260 that allows us to inspect the internal workings of a program in a much more 116 00:06:24,260 --> 00:06:25,700 detailed way. 117 00:06:25,700 --> 00:06:28,810 >> We can actually execute GDB from the command line 118 00:06:28,810 --> 00:06:35,370 here by simply typing GDB and the command that we want to debug. 119 00:06:35,370 --> 00:06:37,550 In this case, count. 120 00:06:37,550 --> 00:06:41,650 Now in this case, we can see that it brings us to a prompt that says GDB. 121 00:06:41,650 --> 00:06:44,020 And we can actually execute commands to GDB 122 00:06:44,020 --> 00:06:48,260 to actually begin execution of the program, stop it at certain points, 123 00:06:48,260 --> 00:06:51,060 evaluate the variables and inspect the variables that 124 00:06:51,060 --> 00:06:54,152 exist in the program state at that particular moment, 125 00:06:54,152 --> 00:06:55,110 and so on and so forth. 126 00:06:55,110 --> 00:06:57,240 It provides a lot of power to us. 127 00:06:57,240 --> 00:06:59,960 >> But it just so happens that the CS50 IDE also 128 00:06:59,960 --> 00:07:05,870 provides a GUI or a user interface for GDB that 129 00:07:05,870 --> 00:07:11,120 allows us to do this without needing the command line interface whatsoever 130 00:07:11,120 --> 00:07:13,560 or at all even. 131 00:07:13,560 --> 00:07:16,930 The way that I can access that is by using the debug button 132 00:07:16,930 --> 00:07:20,120 at the very top of the CS50 IDE. 133 00:07:20,120 --> 00:07:24,280 Now in the past, what we have seen is that we use the command 134 00:07:24,280 --> 00:07:27,660 line to compile and then run a program. 135 00:07:27,660 --> 00:07:29,790 >> The debug button does both of those steps. 136 00:07:29,790 --> 00:07:34,380 But it also will bring up the debugger tab on the far right 137 00:07:34,380 --> 00:07:38,280 that allows us to inspect a variety of properties of the program 138 00:07:38,280 --> 00:07:40,500 as it is executing. 139 00:07:40,500 --> 00:07:44,280 If I click debug, in this case, it will bring up 140 00:07:44,280 --> 00:07:48,230 a new tab in the console window at the very bottom. 141 00:07:48,230 --> 00:07:51,160 >> And you can see that this tab has some information at the very top. 142 00:07:51,160 --> 00:07:52,670 And we can largely ignore this. 143 00:07:52,670 --> 00:07:54,800 But one of the things that we want to notice 144 00:07:54,800 --> 00:07:57,170 is that it outputs the same thing that we 145 00:07:57,170 --> 00:08:03,000 would get if we tried to run make on the C program in the terminal window. 146 00:08:03,000 --> 00:08:06,230 >> Here, we can see it's running clang, and it has a variety of flags, 147 00:08:06,230 --> 00:08:12,660 and it is compiling our count.c file, which was the selected tab at the time 148 00:08:12,660 --> 00:08:15,100 that I hit debug. 149 00:08:15,100 --> 00:08:18,010 So this is very useful because now using this debug button, 150 00:08:18,010 --> 00:08:23,280 we can simultaneously compile and then execute the program that we actually 151 00:08:23,280 --> 00:08:24,460 want to run. 152 00:08:24,460 --> 00:08:27,880 >> One of the flags that is important, in this case, 153 00:08:27,880 --> 00:08:30,190 we've actually been using for the longest time 154 00:08:30,190 --> 00:08:32,450 but also just did some hand waving [INAUDIBLE], which 155 00:08:32,450 --> 00:08:33,820 is this one right here. 156 00:08:33,820 --> 00:08:35,790 In clang, it says -ggdb3. 157 00:08:35,790 --> 00:08:38,570 158 00:08:38,570 --> 00:08:41,250 In this case, what we are telling clang, our compiler, 159 00:08:41,250 --> 00:08:43,820 is that we want to compile our program. 160 00:08:43,820 --> 00:08:46,810 But also provide what are called symbol information 161 00:08:46,810 --> 00:08:50,940 so that the compiler actually has access to a lot of the underlying information 162 00:08:50,940 --> 00:08:52,610 contained within the program. 163 00:08:52,610 --> 00:08:55,260 >> More specifically, the number of functions that I have, 164 00:08:55,260 --> 00:08:58,000 the names of those functions, the variables, the types 165 00:08:58,000 --> 00:09:01,730 that those variables are, and a variety of other things that help the debugger 166 00:09:01,730 --> 00:09:04,350 perform its operation. 167 00:09:04,350 --> 00:09:06,600 Now there's something else that's important to mention 168 00:09:06,600 --> 00:09:10,280 when we're discussing running a program in this way. 169 00:09:10,280 --> 00:09:13,660 >> Notice that it has actually brought up a new tab in our console 170 00:09:13,660 --> 00:09:14,780 along the bottom. 171 00:09:14,780 --> 00:09:18,600 We no longer have to interact directly with the terminal window. 172 00:09:18,600 --> 00:09:21,420 But this new tab is actually a terminal window. 173 00:09:21,420 --> 00:09:26,710 It just is specific to the running program that we have created. 174 00:09:26,710 --> 00:09:29,270 >> Notice that at the bottom, in combination with some output 175 00:09:29,270 --> 00:09:33,500 by clang the compiler and GDB, which we can largely ignore, 176 00:09:33,500 --> 00:09:37,570 it actually shows the output of our program at the very bottom. 177 00:09:37,570 --> 00:09:41,240 Now it's important to realize that this one window actually 178 00:09:41,240 --> 00:09:43,360 will show you the output from your program 179 00:09:43,360 --> 00:09:47,190 but also can accept input for that program, as well. 180 00:09:47,190 --> 00:09:49,260 >> So notice that says please enter a number, 181 00:09:49,260 --> 00:09:53,050 which is the same output that we had had in the terminal window before. 182 00:09:53,050 --> 00:09:55,510 But it's now shown in this new tab. 183 00:09:55,510 --> 00:09:56,550 I can input a number. 184 00:09:56,550 --> 00:10:00,900 And it will actually function as we expect 185 00:10:00,900 --> 00:10:05,890 showing us our debug, output, the output that might be buggy, 186 00:10:05,890 --> 00:10:07,010 as we've seen before. 187 00:10:07,010 --> 00:10:10,460 And at the very bottom, it actually has some additional output 188 00:10:10,460 --> 00:10:14,550 from GDP just saying that this program has completed. 189 00:10:14,550 --> 00:10:16,655 >> Now as you saw in this particular run through, 190 00:10:16,655 --> 00:10:19,370 it wasn't particularly useful because even 191 00:10:19,370 --> 00:10:23,740 though we had the debugger menu come up, this was still a running program. 192 00:10:23,740 --> 00:10:26,790 At no point did it actually pause execution for us 193 00:10:26,790 --> 00:10:30,767 to be able to inspect all of the variables contained within. 194 00:10:30,767 --> 00:10:32,850 There's something else that we have to do in order 195 00:10:32,850 --> 00:10:36,910 to get GDB to recognize that we want to pause execution of the program 196 00:10:36,910 --> 00:10:42,820 and not just allow it to proceed normally as we would in any other case. 197 00:10:42,820 --> 00:10:45,530 >> In order to pause execution, at some specific line, 198 00:10:45,530 --> 00:10:47,830 we need to create what's called a break point. 199 00:10:47,830 --> 00:10:52,670 And a break point is very easily created in this CS50 IDE by taking your mouse 200 00:10:52,670 --> 00:10:57,090 and clicking directly to the left of some specific line number. 201 00:10:57,090 --> 00:10:59,920 Once I do that, a red dot appears, which indicates 202 00:10:59,920 --> 00:11:02,300 that that line is now a break point. 203 00:11:02,300 --> 00:11:07,540 >> And the next time that I run GDB, it will stop execution at that break point 204 00:11:07,540 --> 00:11:10,280 when it reaches that line of code. 205 00:11:10,280 --> 00:11:12,230 Now this is an important thing to realize 206 00:11:12,230 --> 00:11:16,140 that it's not necessarily the case that every line of code 207 00:11:16,140 --> 00:11:17,880 is actually accessible. 208 00:11:17,880 --> 00:11:23,780 If I were to create a function up here, for example-- void f-- 209 00:11:23,780 --> 00:11:31,230 and just do a print line here-- hello world-- if I never call this function, 210 00:11:31,230 --> 00:11:34,770 it will be the case that, if I set a break point here, 211 00:11:34,770 --> 00:11:36,220 the function will never be called. 212 00:11:36,220 --> 00:11:38,310 And therefore, this particular break point 213 00:11:38,310 --> 00:11:43,040 will never actually pause execution of the program. 214 00:11:43,040 --> 00:11:48,020 >> So let's say that I correctly create a break point on some line of code 215 00:11:48,020 --> 00:11:50,340 that will actually be executed. 216 00:11:50,340 --> 00:11:53,470 Now in this case, this is the first line in the main function. 217 00:11:53,470 --> 00:11:56,630 So it will certainly be the case that, as soon as I begin execution, 218 00:11:56,630 --> 00:11:58,580 the very first line will be reached. 219 00:11:58,580 --> 00:12:00,230 GDB will pause execution. 220 00:12:00,230 --> 00:12:04,100 And then, I will be able to interact with the debugger. 221 00:12:04,100 --> 00:12:08,480 >> You can set multiple lines as breakpoints, if you would like. 222 00:12:08,480 --> 00:12:11,365 We can also create a line up here in this segment of code 223 00:12:11,365 --> 00:12:12,490 that will never be reached. 224 00:12:12,490 --> 00:12:14,744 And we can also set one further below. 225 00:12:14,744 --> 00:12:16,660 The reason that we would want to do this we'll 226 00:12:16,660 --> 00:12:19,119 go into a little bit more detail in just a moment. 227 00:12:19,119 --> 00:12:21,660 So for now, let me just disable these additional break points 228 00:12:21,660 --> 00:12:24,940 so that we can look at what happens when I have one single break 229 00:12:24,940 --> 00:12:27,650 point in my program. 230 00:12:27,650 --> 00:12:29,410 I have made some changes to this program. 231 00:12:29,410 --> 00:12:30,750 So I need to save it. 232 00:12:30,750 --> 00:12:34,490 I will click debug so that I can begin the compilation and then 233 00:12:34,490 --> 00:12:36,880 execution of the debugger. 234 00:12:36,880 --> 00:12:40,632 >> We will see that, after moments, the line that we selected as the break 235 00:12:40,632 --> 00:12:43,360 point is highlighted in yellow. 236 00:12:43,360 --> 00:12:47,440 We can also notice that in the upper right in the debug panel 237 00:12:47,440 --> 00:12:50,940 that the pause icon has turned into a little play icon. 238 00:12:50,940 --> 00:12:54,710 This means that we have pause execution, in this particular case. 239 00:12:54,710 --> 00:12:57,840 And hitting the Play button would allow us to resume execution 240 00:12:57,840 --> 00:13:00,000 at that specific point. 241 00:13:00,000 --> 00:13:03,240 >> Notice that there's a couple of other buttons available in this debug panel, 242 00:13:03,240 --> 00:13:04,220 as well. 243 00:13:04,220 --> 00:13:09,470 Step over, which allows me to execute that one line of code 244 00:13:09,470 --> 00:13:14,030 and step over to that line to the next one, which, in this case, 245 00:13:14,030 --> 00:13:17,060 would mean that the printf statement is executed. 246 00:13:17,060 --> 00:13:22,310 And it will then pause execution on line 13, like so. 247 00:13:22,310 --> 00:13:25,090 >> And there's also a step into function, which 248 00:13:25,090 --> 00:13:28,950 is useful if I have created other functions elsewhere in the source code. 249 00:13:28,950 --> 00:13:31,420 And I want to step into those functions rather than 250 00:13:31,420 --> 00:13:33,050 execute that function as a whole. 251 00:13:33,050 --> 00:13:37,279 But we'll look more at the step into function in just a moment. 252 00:13:37,279 --> 00:13:40,320 Now notice some other things that actually exist within this debug panel. 253 00:13:40,320 --> 00:13:44,110 >> We have this panel called the call stack, which shows us 254 00:13:44,110 --> 00:13:45,300 where exactly we are. 255 00:13:45,300 --> 00:13:48,550 In this case, we are inside of the main function. 256 00:13:48,550 --> 00:13:50,880 Our script is called count.c. 257 00:13:50,880 --> 00:13:53,820 And we happen to be on line 13, column one, which 258 00:13:53,820 --> 00:13:58,950 is precisely what the highlighted region of the source code indicates, as well. 259 00:13:58,950 --> 00:14:02,435 >> Now notice that this also shows under the local variable section 260 00:14:02,435 --> 00:14:06,710 all of the variables that exist within this function. 261 00:14:06,710 --> 00:14:08,930 It's important to note that all of the variables 262 00:14:08,930 --> 00:14:12,580 will appear in this local variable section within a function, 263 00:14:12,580 --> 00:14:14,380 even before they are defined. 264 00:14:14,380 --> 00:14:19,160 We can see here that we have a variable called num, has a default value of 0, 265 00:14:19,160 --> 00:14:21,280 and it is of type int. 266 00:14:21,280 --> 00:14:24,110 >> Now before we actually initialize all of these variables, 267 00:14:24,110 --> 00:14:26,685 we're not necessarily guaranteed to see a value of 0. 268 00:14:26,685 --> 00:14:29,200 And depending on other executions that you have performed 269 00:14:29,200 --> 00:14:32,020 and the state of your memory when you actually run this program, 270 00:14:32,020 --> 00:14:34,605 you might find that you don't see values of 0 271 00:14:34,605 --> 00:14:36,550 and, instead, some other crazy numbers. 272 00:14:36,550 --> 00:14:38,390 >> But don't worry about that. 273 00:14:38,390 --> 00:14:44,610 It's not going to be relevant until you actually initialize the value. 274 00:14:44,610 --> 00:14:49,630 Now in this case, we can see that I have performed some outputs. 275 00:14:49,630 --> 00:14:52,131 And I'm, right now, paused execution. 276 00:14:52,131 --> 00:14:53,880 But in this case, what I really want to do 277 00:14:53,880 --> 00:14:58,060 is to now step over this line of code so that I can actually 278 00:14:58,060 --> 00:15:04,390 query the user for that int that we want to use in our program. 279 00:15:04,390 --> 00:15:07,060 >> Now in this case, when I hit step over, notice 280 00:15:07,060 --> 00:15:11,940 that the Pause or rather the Resume button has changed to this Pause button 281 00:15:11,940 --> 00:15:14,022 because this code is actually executing. 282 00:15:14,022 --> 00:15:15,730 What is happening right now is that it is 283 00:15:15,730 --> 00:15:21,630 waiting for us to input some information as we can see by our output text 284 00:15:21,630 --> 00:15:23,600 at the very bottom. 285 00:15:23,600 --> 00:15:25,787 >> So right now, this is not actually paused, 286 00:15:25,787 --> 00:15:28,620 even though it, sort of, appears to be because nothing is happening. 287 00:15:28,620 --> 00:15:32,360 But it just so happens that in my specific case on line 13, 288 00:15:32,360 --> 00:15:34,210 I'm waiting for user input. 289 00:15:34,210 --> 00:15:39,130 And so GDB is not able to inspect a program as it is running. 290 00:15:39,130 --> 00:15:43,370 >> Now the next time that I enter some input-- so I'll enter that number 5, 291 00:15:43,370 --> 00:15:46,140 as we've seen in the past-- hit Return, and we 292 00:15:46,140 --> 00:15:51,430 notice that, immediately, GDB pauses and, again, highlights the next line. 293 00:15:51,430 --> 00:15:55,320 But notice that now, as a result of our inputting a value, 294 00:15:55,320 --> 00:15:58,930 we have updated that value inside of our local variables, which 295 00:15:58,930 --> 00:16:05,560 is very useful to know precisely what that number was in memory. 296 00:16:05,560 --> 00:16:10,650 >> Now I can allow this program to continue playing until the end of its execution 297 00:16:10,650 --> 00:16:12,570 by hitting Resume. 298 00:16:12,570 --> 00:16:16,410 We can see that very quickly does the program finish executing 299 00:16:16,410 --> 00:16:19,790 with the same output that we had before, the debugger closes, 300 00:16:19,790 --> 00:16:23,170 and now this program has stopped completely. 301 00:16:23,170 --> 00:16:25,320 >> I show that only for the purposes of seeing what 302 00:16:25,320 --> 00:16:27,280 happens when we actually hit Resume. 303 00:16:27,280 --> 00:16:30,640 But we actually are going to want to go back into this program 304 00:16:30,640 --> 00:16:33,820 so that we can try to debug precisely what is happening. 305 00:16:33,820 --> 00:16:37,980 Now that I'm using the debugger, I may not need these debug printf statements. 306 00:16:37,980 --> 00:16:43,860 >> So I could remove them as I will do now just to go back to our simpler code 307 00:16:43,860 --> 00:16:45,950 that we had a moment ago. 308 00:16:45,950 --> 00:16:48,790 Now when I save the program and execute it, 309 00:16:48,790 --> 00:16:53,700 it will, again, go to that initial break point that I had on line 11. 310 00:16:53,700 --> 00:16:57,700 And I'll be able to inspect my variables as I want to do. 311 00:16:57,700 --> 00:17:00,695 >> It just so happens that this part isn't very interesting, 312 00:17:00,695 --> 00:17:04,364 And I know that I'm going to print out this statement. 313 00:17:04,364 --> 00:17:05,280 Please enter a number. 314 00:17:05,280 --> 00:17:08,099 And then, I know that I'm going to ask the user for that integer. 315 00:17:08,099 --> 00:17:13,329 So perhaps, I actually want to move my break point a little bit further down. 316 00:17:13,329 --> 00:17:16,710 >> You can remove break points by clicking, again, directly 317 00:17:16,710 --> 00:17:18,460 to the left of that line number. 318 00:17:18,460 --> 00:17:22,200 That red dot will disappear, indicating that that break point is now gone. 319 00:17:22,200 --> 00:17:24,780 Now in this case, execution has been paused. 320 00:17:24,780 --> 00:17:27,770 And so it's not actually going to resume in that particular instance. 321 00:17:27,770 --> 00:17:30,210 But I can set a break point a little bit later. 322 00:17:30,210 --> 00:17:33,880 >> And when I now resume my code, it will resume and tell 323 00:17:33,880 --> 00:17:36,190 the point of that break point. 324 00:17:36,190 --> 00:17:37,374 Again, I hit Resume. 325 00:17:37,374 --> 00:17:39,040 Doesn't seem like anything is happening. 326 00:17:39,040 --> 00:17:41,450 But that's because my code is waiting for input. 327 00:17:41,450 --> 00:17:47,900 I will enter a number 5, hit Enter, and now the next break point will be hit. 328 00:17:47,900 --> 00:17:50,570 >> Now in this case, this is the line of code 329 00:17:50,570 --> 00:17:53,820 that, before, we knew happened to be buggy. 330 00:17:53,820 --> 00:17:57,590 So let's evaluate what happens at this particular point in time. 331 00:17:57,590 --> 00:18:02,620 When a line is highlighted, this line has not yet been executed. 332 00:18:02,620 --> 00:18:06,490 So in this case, we can see that I have a number, which 333 00:18:06,490 --> 00:18:11,610 I have an integer called num that has a value 5. 334 00:18:11,610 --> 00:18:15,090 And I'm going to be performing some math on that number. 335 00:18:15,090 --> 00:18:20,130 >> If I step over that, we can notice that the value for num 336 00:18:20,130 --> 00:18:23,780 has changed in accordance with the arithmetic that we've actually done. 337 00:18:23,780 --> 00:18:26,810 And now that we are inside of this for loop 338 00:18:26,810 --> 00:18:29,090 or now that the for loop itself is highlighted, 339 00:18:29,090 --> 00:18:32,450 we see that we have a new variable called i that 340 00:18:32,450 --> 00:18:35,370 is going to be used in that for loop. 341 00:18:35,370 --> 00:18:38,230 >> Now remember before that I mentioned that sometimes you're 342 00:18:38,230 --> 00:18:43,470 going to see some kind of crazy numbers as default before that number 343 00:18:43,470 --> 00:18:45,530 or that variable is actually initialized. 344 00:18:45,530 --> 00:18:49,040 We can see that precisely here in the this variable 345 00:18:49,040 --> 00:18:51,345 called i, which has not yet been initialized 346 00:18:51,345 --> 00:18:53,560 at the time of highlighting. 347 00:18:53,560 --> 00:18:57,070 But we can see that it has some number that we wouldn't actually expect. 348 00:18:57,070 --> 00:18:57,620 >> That's OK. 349 00:18:57,620 --> 00:18:59,661 Don't worry about it because we have not actually 350 00:18:59,661 --> 00:19:04,970 initialized that number until I step over this line and the value 351 00:19:04,970 --> 00:19:08,560 i has been initialized to the value 1. 352 00:19:08,560 --> 00:19:11,400 So to see that that's actually the case, let's step over. 353 00:19:11,400 --> 00:19:14,420 We can now see that that line has been executed. 354 00:19:14,420 --> 00:19:17,000 And we are now highlighting this printf line. 355 00:19:17,000 --> 00:19:22,230 >> And we can now see how our values of i and 3 have changed over time. 356 00:19:22,230 --> 00:19:26,450 This is very useful to do, in fact, is to step over lines repeatedly. 357 00:19:26,450 --> 00:19:30,480 And you can find what actually happens inside of your for loop 358 00:19:30,480 --> 00:19:33,660 and what happens to the variables inside of that for loop 359 00:19:33,660 --> 00:19:39,200 as that program execution occurs one step at a time. 360 00:19:39,200 --> 00:19:41,110 >> Now at this point, I stepped over just enough 361 00:19:41,110 --> 00:19:44,210 that I now am at the end of my program. 362 00:19:44,210 --> 00:19:46,980 If I step over that, it will actually cease execution 363 00:19:46,980 --> 00:19:48,860 as we have seen in the past. 364 00:19:48,860 --> 00:19:52,110 Let me restart this, yet again, so that I can point something else out, 365 00:19:52,110 --> 00:19:53,320 as well. 366 00:19:53,320 --> 00:19:55,350 >> In this case, it is now asking me, again, 367 00:19:55,350 --> 00:19:57,100 for a number, which I will, again, enter. 368 00:19:57,100 --> 00:20:00,300 But this time, I'm going to enter in a larger number so that the for loop 369 00:20:00,300 --> 00:20:02,540 will iterate more times. 370 00:20:02,540 --> 00:20:06,090 In this case, I'm going to enter a value of 11. 371 00:20:06,090 --> 00:20:08,390 >> Now again because I'd set a break point at line 15, 372 00:20:08,390 --> 00:20:10,490 it's going to highlight that line. 373 00:20:10,490 --> 00:20:12,980 We can see that our number 11 is correctly 374 00:20:12,980 --> 00:20:15,560 represented in our local variables. 375 00:20:15,560 --> 00:20:22,460 Stepping over that, we can now watch what happens to our value of i 376 00:20:22,460 --> 00:20:25,680 as we proceed inside of this for loop. 377 00:20:25,680 --> 00:20:31,960 It gets incremented every time we reach the top of that for loop. 378 00:20:31,960 --> 00:20:35,110 >> Now one of the things that might be useful to do during execution 379 00:20:35,110 --> 00:20:40,490 of this program is for me to actually change the variables midstream to see 380 00:20:40,490 --> 00:20:42,450 what happens to my program. 381 00:20:42,450 --> 00:20:46,540 In this case, I can actually double click the value. 382 00:20:46,540 --> 00:20:48,040 Notice that it becomes a text field. 383 00:20:48,040 --> 00:20:50,280 >> Now I can enter different value altogether 384 00:20:50,280 --> 00:20:55,700 to see how my program behaves when I've changed that variable. 385 00:20:55,700 --> 00:20:59,560 Now in this case, the variable i now contains the value 10. 386 00:20:59,560 --> 00:21:02,810 But the program is still paused in execution. 387 00:21:02,810 --> 00:21:07,610 When I step over, I see that the value i, which I entered as 10, 388 00:21:07,610 --> 00:21:12,170 is not greater than the value of num, which immediately causes the for loop 389 00:21:12,170 --> 00:21:14,240 to stop executing. 390 00:21:14,240 --> 00:21:16,210 >> Now that's not the only reason why you would 391 00:21:16,210 --> 00:21:19,450 want to modify the variable in place. 392 00:21:19,450 --> 00:21:22,210 You might actually want to try to modify it so 393 00:21:22,210 --> 00:21:24,590 that you can continue execution of a loop 394 00:21:24,590 --> 00:21:27,370 or so that you can modify some value before it 395 00:21:27,370 --> 00:21:32,630 reaches some specific set of arithmetic that you are about to perform. 396 00:21:32,630 --> 00:21:36,210 >> So now that we actually change the value of i as the program was executing, 397 00:21:36,210 --> 00:21:39,540 it caused the for loop to quit prematurely because, all of a sudden, i 398 00:21:39,540 --> 00:21:42,770 happened to be greater than the value of num, meaning that that for loop 399 00:21:42,770 --> 00:21:45,410 no longer needed to be executed. 400 00:21:45,410 --> 00:21:48,780 Further, it happened to be the case that we changed the value of i 401 00:21:48,780 --> 00:21:53,270 when the line 17 was highlighted, which was the point in time 402 00:21:53,270 --> 00:21:56,280 that the for loop execution was actually being evaluated. 403 00:21:56,280 --> 00:22:00,210 >> If I had changed the value of i on a different line, say 19, 404 00:22:00,210 --> 00:22:03,360 we would have seen different behavior because line 19 would 405 00:22:03,360 --> 00:22:08,310 have executed before the loop condition was reevaluated. 406 00:22:08,310 --> 00:22:11,900 Now at this point, I'm, again, at the end of this program. 407 00:22:11,900 --> 00:22:15,707 And I can allow this to proceed to allow my program to quit naturally. 408 00:22:15,707 --> 00:22:18,290 But there's a couple of things that are important to take away 409 00:22:18,290 --> 00:22:19,960 from this particular discussion. 410 00:22:19,960 --> 00:22:22,490 You need to evaluate your own assumptions 411 00:22:22,490 --> 00:22:24,710 about how the code should be behaving. 412 00:22:24,710 --> 00:22:28,220 Any time you think that some piece of code you know happens to work, 413 00:22:28,220 --> 00:22:30,940 that might be a red flag to go back and evaluate, and be sure 414 00:22:30,940 --> 00:22:33,470 that your assumption of how that code is operating 415 00:22:33,470 --> 00:22:38,290 is actually true to how it is expressed in your source code. 416 00:22:38,290 --> 00:22:41,300 >> But even more to point was, when we are using the debugger, 417 00:22:41,300 --> 00:22:43,920 you can put breakpoints at different lines of code, 418 00:22:43,920 --> 00:22:48,110 which will cause the debugger to pause execution at each of those lines 419 00:22:48,110 --> 00:22:52,210 so that you can evaluate the memory or even change it in place. 420 00:22:52,210 --> 00:22:55,630 And again, remember that you can create multiple breakpoints so that you 421 00:22:55,630 --> 00:23:00,390 can also resume execution, skip over large portions of code, 422 00:23:00,390 --> 00:23:04,790 and it'll automatically pause at the next break point. 423 00:23:04,790 --> 00:23:07,760 >> There's actually more advanced features of the debugger, as well. 424 00:23:07,760 --> 00:23:10,170 But we'll have to refer you to some subsequent videos 425 00:23:10,170 --> 00:23:14,090 in order to really tease apart how to use those particular functions. 426 00:23:14,090 --> 00:23:15,990 For now, thank you very much for watching. 427 00:23:15,990 --> 00:23:18,080 And good luck debugging.