Placeholder Image

字幕列表 影片播放

  • DOUG LLOYD: So if you're anything like me, when you write code

  • it's not always going to be perfect.

  • There's usually going to be something wrong with it.

  • And that is known as writing bugs.

  • And part of being a computer programmer is

  • learning how to debug, or remove the bugs, from programs.

  • And there are a lot of different techniques and strategies

  • that one might use to do this.

  • And what I want to do in this video is show you

  • three of the tools that are baked into CS50 IDE

  • that you can use to help with your debugging,

  • or help trying to figure out what's going on in your system.

  • And these three tools, which I'm going to just display the names of here,

  • are known as debug50, eprintf, and help50.

  • We're actually going to cover those in reverse order.

  • So we're going to start with help50.

  • So I have a couple of files pre-configured in my IDE.

  • I'm going to navigate into my help50 directory.

  • And just clear the terminal window here.

  • And what help50 basically does, it is designed

  • to be sort of a virtual teaching fellow of sorts.

  • It basically is trying to give you clues and hints about what might be going on

  • in your program or when you're trying to work with your program

  • and something goes wrong without just giving you the answer outright.

  • So it's trying to nudge you along in the right direction in the hopes

  • that it's an issue that, with a little bit of encountering and having

  • the computers sort of give you a little bit of back and forth,

  • it's an issue that you'll learn to be able to not recreate in the future.

  • So I have a couple of example programs here.

  • All of them are written in C. And let's just try and compile the first one.

  • So let's try and make example one.

  • Error.

  • So this is where help50 is going to come in handy.

  • Generally it's going to be used when you're working.

  • It's not so much a bug in your program that is

  • during runtime, a runtime error.

  • This is going to be a logical bug, or some kind

  • of bug that prevents your program from being compiled

  • is going to be the most common use case of help50.

  • So here I'm getting told I'm implicitly declaring library function

  • printf with blah, blah, blah.

  • There's a whole lot of text there.

  • Now, what help50 tries to do is it looks at that error message for you.

  • And if there are multiple ones it will look

  • at the first error message for you.

  • And it will try and translate that kind of arcane language

  • into something a little more, hopefully, intuitive to use.

  • And the way we use help50 is pretty straightforward.

  • We first type help50, and then we do exactly the command we tried to do.

  • So in this case it's help50, make example1.

  • Let's see if maybe help50 can give me a little more information about what

  • I might be doing wrong in my program.

  • So I run it again.

  • Now, I'm getting this sort of hint from the virtual TF,

  • which is written here in yellow.

  • "Did you forget to #include stdio.h in which printf

  • is declared atop your file?"

  • Well, let's take a look.

  • So in example 1.c, it looks like I did kind of forget to do that.

  • So if I just go ahead and add that, and I save,

  • and I try and make example one again maybe.

  • Hey, it compiled.

  • It worked just fine.

  • So I can now run the example1 program, hello world.

  • Now, of course, I have a logical bug here where I didn't put a backslash n.

  • So it kind of ran into a new line like that.

  • But that's OK.

  • That's something I can go ahead and fix pretty easily.

  • So let's try and compile example two.

  • And we'll go through this again where we won't look at the source code

  • beforehand.

  • We'll just try and compile it, thinking we're pretty close,

  • and see what happens.

  • So we'll try and make example2.

  • Oh.

  • Seven errors generated.

  • That's not good.

  • But, again, help50 can help us here.

  • And what it's going to do in this case is

  • it's going to look at the very first one and give us a hint for that one.

  • Now, oftentimes when you get a lot of errors from compiling

  • it's not necessarily that I've done seven things wrong.

  • In fact, if you look at the program you'll

  • see that it's not that many lines of code when we do.

  • But really it's just one error that sort of cascades and creates

  • another one because it doesn't understand what's happening before.

  • And if you can fix that one error at the beginning,

  • it might resolve one or more, or all, of the remaining errors.

  • So I'll clear my terminal window.

  • And we'll try this again.

  • But we'll preface this by saying help50 first.

  • So help50 make example2.

  • Let's see.

  • Use of undeclared identifier string.

  • Did you mean standard in?

  • Well, I'm assuming probably not.

  • Let's take a look at my code.

  • No.

  • I meant to use string there on line five.

  • So by undeclared identifier, Clang means you've used a name string

  • on line five which hasn't been defined.

  • Did you forget to #include cs50.h in which string is defined atop your file?

  • Well, here, again, I did.

  • I did forget to include cs50.h this time.

  • So it gave me another clue here.

  • But I had seven errors.

  • So hopefully this resolves most of them.

  • Lets clear this and see if it does.

  • We'll try and make example2 again.

  • And it did.

  • So even though it said I had seven errors, I really didn't.

  • I just had the one.

  • And because that one kind of threw everything else off,

  • it just kind of cascaded down and really messed us up.

  • All right.

  • Let's take a look at example three.

  • We'll try and make example three.

  • Seven errors again.

  • Ugh, man.

  • Let's see what I got here.

  • Looks like I have a for loop that's going from 1 to 10.

  • And it's supposed to print out a new integer on each line.

  • That looks OK to me, at least at first glance.

  • I don't really know what the issue could be here.

  • But help50 might be able to help us out again.

  • So we'll try one more time help50 make example3.

  • And, again, you'll see that help50 is commonly

  • going to be used most of the time-- although it's not all it can do.

  • And we'll take a look at a couple of examples of that in a second.

  • You're going to use help50 most of the time when there are compile time

  • errors that prevent your program from being compiled

  • and have to be resolved first.

  • So we'll try and help50 this one.

  • Looks like it says on line five it looks like you're

  • trying to declare a variable that's already been declared elsewhere.

  • I don't see that.

  • But then it tells me a little bit more.

  • If you meant to create a for loop be sure that each part is separated

  • with a semicolon rather than a comma.

  • So here I've got commas, and I'm supposed to have semicolons.

  • So it's, again, little things like this where it's little syntax things where

  • if you were able to get in touch with somebody

  • you could just kind of look at your code really quickly and be like,

  • oh, well, you really just need to put in a semicolon here instead of a comma.

  • That's the kind of thing where it stinks to get stuck in a jam where you're just

  • waiting for somebody to give you that sort of shining moment right

  • where suddenly the error is revealed.

  • You can use help50 to try and help you along and accelerate this

  • so that you don't get stuck waiting, and you can get a little resolution

  • for your errors a little more quickly.

  • Of course, we'll just confirm with trying to make it again.

  • And it compiled no problem.

  • I could run this program.

  • And it will print out the numbers 1 through 10, each on separate lines.

  • We can't see them all here because my terminal window is not big enough

  • to hold them, but they're all there.

  • All right.

  • I got one more example here.

  • And then I'll show you two examples of using help50 not in the make context

  • necessarily, or in the Clang context.

  • So let's try and make example4.

  • I have one error.

  • "Expression result unused, n times 5."

  • Not really sure what that means.

  • So let's just quickly pop open example4 here at the top.

  • Looks like what I want to do is have this print out 50.

  • So I set n as equal to 10.

  • I multiply n by 5 to get 50.

  • And I want to print out 50.

  • So I wonder what the issue could be.

  • So let's help50 make example4.

  • On line six of example 4.c you are performing an operation,

  • but not saving the result. Did you mean to print or store

  • the result in a variable?

  • So remember, when we are doing mathematical manipulations

  • to variables, we always have to assign the result to something.

  • And here what I probably meant to say is either n equals n times 5,

  • to change n from 10 into 50, or the more shorthand version,

  • n times equals 5, which would also work just fine.

  • So I can save this.

  • Hopefully this fixes it.

  • I'll try and recompile it.

  • And I'll try and run it to see if I get 50 printed out.

  • So that's a couple of uses of, in particular

  • this is help50 helping with Clang.

  • Although every time we were doing this we were typing make.

  • Remember that make is actually just a wrapper

  • for Clang, which is the name of the actual compiler

  • that we're using in CS50 IDE.

  • What happens though if I try and do this?

  • There's no file called example5.

  • So make example5.

  • Unlike the previous four, this is actually

  • going to be a help50 that helps with a message

  • from make as opposed to a message from Clang.

  • Now, obviously it's not there.

  • So you can probably figure out what it means.

  • But in case you didn't, I could preface it with help50.

  • "Do you actually have a file called example5.c in the current directory?"

  • Well, I don't.

  • So I'm trying to compile a program that doesn't exist.

  • So this is just help50, again, giving me a clue,

  • like, well, maybe you're making a little bit of a mistake here.

  • And it's true.

  • I am making a bit of a mistake.

  • One more example here.

  • Let's say that I want to change directories into another directory.

  • So I want to ls example6.

  • There is, again, no example6 here.

  • "ls cannot access example6, no such file or directory."

  • Again, help50 might be able to help with this.

  • So I'll preface it one more time.

  • Are you sure example6 exists?

  • Did you misspell example6?

  • It doesn't exist.

  • Maybe I had typed it wrong and I thought it was working.

  • So it's just a reminder.

  • Did you check that?

  • Oh, maybe I had misspelled it.

  • Maybe I meant to do something else, and then I can take a look.

  • Now, help50 is a tool that is still in development.

  • We actually have an open source GitHub repository.

  • So as you go through the class and you become more comfortable, particularly

  • as you start to learn Python, which is the tool that help50 is written in,

  • you can actually head to CS50's public GitHub repositories and take a look

  • and see what types of error messages that

  • are a little more arcane that we're trying to catch and have help50

  • explain in more human understandable terms

  • so that if you want to contribute to that you actually can.

  • And if you encounter an error that you're not

  • getting, that help50 doesn't understand, and you want to report that error

  • and hope that somebody else maybe can help match it,

  • you can do that through that platform as well.

  • So this is definitely a collaborative tool.

  • And we welcome you to continue to contribute either solutions as you

  • become more comfortable, or issues that we can try and resolve

  • to make it a more robust tool.

  • All right.

  • So another tool that we have is one called eprintf.

  • Now, it's really common when you are starting to debug your programs to kind

  • of pepper them with printf statements.

  • It's sort of like a sanity check where you're checking,

  • OK, well, this line printed.

  • And then I have some lines of code that run.

  • And then this line printed.

  • Like you're trying to figure out where things are going wrong.

  • The trouble with printf is it doesn't necessarily tell you

  • where the program is going wrong.

  • You have to kind of go back and scroll through your source code

  • to figure out which error message corresponds to that.

  • That's not always that helpful.

  • It's not a huge deal.

  • But we have this tool that makes it a little bit easier.

  • So it's called eprintf, which stands for error printf.

  • And I'm just going to navigate into my eprintf directory

  • where I have just one example file.

  • I'm going to open that up here and show you what it does.

  • So not much to this.

  • I'm going to scroll up here.

  • Basically what I'm doing is I'm asking the user to give me an integer.

  • And then I actually get that integer from them.

  • And then I have eprintf, integer obtained.

  • Now, this means nothing to the user.

  • It's an error message to make sure for me,

  • as the person who's testing this program, that I got to this point

  • in the program.

  • And we'll see exactly what eprintf does that gives it

  • a little bit of a leg up over printf, which is just

  • going to display to the terminal.

  • Then I'm doing a couple of different things.

  • If x is less than 0, I'm going to print x is negative.

  • If it's greater than zero, I print x is positive.

  • Otherwise I print x is 0.

  • And then I have one more eprintf call at the bottom here

  • which is got through the program.

  • So if I see that eprintf, that means that I've succeeded

  • and I've gotten through every single line of the program without crashing.

  • So let's just quickly compile this with make eprintf.

  • And we'll try and run ./eprintf.

  • Please give me an integer.

  • Let's give it 50.

  • And look at the little difference here.

  • So instead of just printing out what I said, it tells me where it came from.

  • So it tells me what line it came from and what file it came from.

  • As we write more and more complex programs later in the course,

  • we might write programs that span multiple .c files.

  • We might have eprintfs throughout them.

  • So it's just a useful way to figure out exactly from where in your program,

  • or as things are going through, where in your program

  • the error message that you're seeing, or sort of the printf

  • prompt that you're seeing comes from.

  • So it's definitely a good tool to familiarize yourself with,

  • particularly earlier on where you might not

  • need the more complex tools of a debugger, which

  • we're going to talk about in a second.

  • But you just want to get sort of a sanity check

  • to make sure that things are working the way you expect them to.

  • OK.

  • And the third and final tool that we're going to cover in this video

  • is debug50.

  • Now, debug50 is a GUI or Graphical User Interface

  • wrapper for a tool known as GDB, which is a very richly developed debugging

  • platform.

  • And it will really help you take a look underneath the hood,

  • inspect what is going on in your program,

  • and try and figure out where things might be going wrong.

  • In this example we're going to cover three different buggy videos.

  • And I'm going to show you how to use debug50

  • to sort of give you some clues as to what you might need to do.

  • So the first thing I'm going to do here is navigate into my debug50 directory

  • where I have three source files and three programs that are previously

  • compiled.

  • So these have compiled.

  • I don't need help50 to tell me what's going on here

  • because I've already got the compiled binaries here.

  • But there's something going wrong in these programs that

  • is not what I expect.

  • So the first thing I want to do is run debug1's program,

  • and then we'll take a look at debug1's source code.

  • And then we'll take a look at how debug50

  • can give us a little bit more information about what

  • might be going wrong here.

  • So here's what we're going to do.

  • We're going to go, and I'm going to clear my terminal really quick,

  • and we're going to run debug1's binary.

  • Provide a number.

  • OK.

  • I'll provide one.

  • You gave a one.

  • Seems pretty good.

  • Let's try this again.

  • Provide a number.

  • I'll give it two.

  • You gave a one.

  • That's not right.

  • Zero?

  • You gave a one.

  • So it's always saying, I gave a one.

  • I did.

  • I gave a one the first time.

  • So let's maybe take a look at what's going on here.

  • So I have my program.

  • I'm providing a number.

  • OK.

  • That works.

  • If x is one, say you gave a one.

  • Otherwise, apparently I'm not doing anything.

  • It's not supposed to print anything if I didn't give it a one.

  • So that's weird.

  • So at this point if you're familiar with the code

  • you might see where the issue is here.

  • But let's pretend that we don't.

  • Or maybe you don't.

  • And that's totally OK as well.

  • This debug50 tool can hopefully give a little bit more information

  • and we can see what's happening.

  • So what I want to do is the first thing you

  • need to do when you're working with a debugger

  • like GDB is to provide a breakpoint.

  • What a breakpoint is is basically your program

  • will execute until it hits that line of code.

  • And then it will stop, or break, and wait for something to happen.

  • If you don't know where to break in your code,

  • because you don't even know where the issue might be happening,

  • it's totally reasonable to break at main.

  • The way that you set a breakpoint is right here to the left of the line

  • numbers you'll notice that my cursor turned into a little like pointer

  • finger there.

  • If you click once, you get this sort of red light, or a stop light.

  • That's basically your indicator that you have set a breakpoint.

  • So my program will compile, and it will run until it gets to line six.

  • At which point it's going to kind of freeze.

  • And from there I can make very slow steps through my program.

  • Usually when we're running our program it's like you compile it,

  • and it's done.

  • Here we can really force it to slow down, and look

  • what it's doing line, by line, by line, and see if we

  • can see where the issue might lie.

  • So I've set a breakpoint.

  • Now I need to run debug50.

  • debug50 ./debug1.

  • Cause that's the name of the program that I wanted to test.

  • Hit Enter.

  • And if you've watched our CS50 IDE tutorial introduction video

  • you noticed I talked about the debugger tab.

  • You'll notice the debugger tab on the right has popped open.

  • And I'm giving a little bit of information here.

  • I have information about the call stacks.

  • So if I had multiple functions being called

  • it would tell me which function I'm in at the time,

  • and which functions are waiting for stuff to happen.

  • Local variables in my program.

  • There are values.

  • What type they are, and so on.

  • Really useful stuff.

  • And my program has frozen, right.

  • It has not printed out "please provide a number."

  • It's just waiting for me to do something.

  • And the way I can control what my program does is up here at the top.

  • I have resume, which is basically just going to speed through my program

  • again, ignoring any more breakpoints.

  • I have step over, which is going to move one line ahead.

  • And generally you're going to want to step over any functions

  • that you did not write, because if you step into them, which

  • is the next example, it's actually going to go and look at printf's code,

  • and start executing printf's code one line at a time.

  • And we can probably assume that printf is OK.

  • And we can probably assume that getint, for example, is OK.

  • So we don't need to step into those.

  • We can step over them.

  • If you're going into a block, for example, like an if, or a function

  • that you wrote, you might want to step into it,

  • unless you happen to know for sure that it's not an issue in that function.

  • So you can start to proceed through those a line at a time.

  • And then, lastly, there's step out.

  • We're not in anything right now.

  • So we can't step out.

  • But if you step into a function and you realize,

  • oh, I really shouldn't have done this, you can step out,

  • which will just proceed through the rest of the function,

  • and then pick up again at the next logical spot.

  • So what I want to do here is start to proceed one line at a time.

  • So I want this to print out "provide a number."

  • So I'm going to step over this line, which is going to execute it.

  • You can see it at the terminal there at the bottom.

  • Then it's prompting me to provide a number.

  • So I'll give it a three.

  • One seems to work.

  • So I'm going to give it a three.

  • And I'll hit Enter.

  • And then I will again step over.

  • If x equals one printf.

  • You gave a one.

  • So I kind of want to step into this.

  • And in particular, notice what's going to happen here.

  • Notice that right now it says my variable x

  • has a value of three, which is what I expect.

  • But as I step into this, the value of x has changed to one.

  • It's no longer three.

  • So this statement is now true.

  • It says, well, x is one.

  • So you gave a one.

  • And if I step over, that is what it will do.

  • You gave a one.

  • And if I stop one more time, the program finishes executing.

  • Did you happen to see what the error there was?

  • It's a silly little syntax thing.

  • But I used a single equal sign instead of a double equal sign.

  • So what I really did here is I assigned x to be one.

  • Regardless of what x was at this point, I said x is equal to one.

  • I assigned x to one, when I really meant to do this.

  • If x equals equals one.

  • And now let's just save this program really quickly.

  • And we'll recompile it, because we have to recompile

  • a program if we want to rerun it.

  • Use equals to turn this comparison into an equality assignment.

  • Now, the reason that this works is because I had put

  • this extra set of parentheses in here.

  • Generally if you tried to do this it wouldn't work.

  • But I had to force it for purposes of this example.

  • So I had to get rid of those parentheses as well.

  • We'll try one more time to compile this program.

  • Now it compiled successfully.

  • We'll clear our terminal window.

  • And let's try and debug50 one more time, just

  • to make sure that everything is working the way we expect.

  • We still have our breakpoint set at line six.

  • So it's still going to freeze at the first possible opportunity after that.

  • I want to step over this to provide a number.

  • I'll give it three again.

  • Step over.

  • x is now equal to three.

  • You can see here on the right.

  • Now, let's step into this.

  • Can't step into it.

  • Why?

  • Because x is not one anymore.

  • So that next line of code on line 13 there

  • is not going to execute because the condition is no longer true.

  • So before I was assigning x to be one.

  • And that's why it would go in.

  • And thanks to debug50 I was able to see, oh, wait, this three

  • is unexpectedly changing into a one.

  • Maybe there's something going on wrong in that area.

  • So that's one way that debug50 was able to help isolate where in the program

  • things were going awry.

  • All right.

  • So I'm going to hit Resume here just to end the program,

  • have it finish doing its thing.

  • Didn't print anything because we didn't have a one.

  • And now let's take a look at program number two.

  • So I'll clear my terminal.

  • And let's try and execute the debug2 program.

  • "What percentage grade did you get as a number?"

  • Well, let's say maybe I wasn't doing so great in CS50 and I got a 50%.

  • My grade is an E.

  • OK.

  • But let's say maybe I'm doing a little bit better and I got a 75.

  • So that should hopefully be like a C. Eh, I got an E.

  • Wait a minute.

  • What if I got like an A, I got everything?

  • E.

  • Well, again, this isn't doing exactly what I expected it to do.

  • So let's take a look at the source code.

  • And then let's take a look at debug50 and see if maybe it

  • can give us some clues here.

  • So I'll open up the source code for debug2.

  • And I'll just close this one here.

  • And I'll also just clear the terminal screen one more time.

  • All right.

  • So what percentage of the grade did you get as a number?

  • Get an integer.

  • What's happening here on line eight is I'm just

  • transforming whatever the user gave me into a multiple of 10,

  • so that divided by 10 times 10, that's a trick that

  • works because of integer division.

  • But say the user gives me 93.

  • 93 divided by 10 is nine, not 9.3.

  • Remember, its integer division.

  • And then 9 times 10 is 90.

  • So I'm just basically dropping off the ones place of every number

  • here and just transforming it into a multiple of 10.

  • And then I have a letter character for a grade.

  • It will get stored there.

  • And then I'm using a switch statement, which

  • is one form of conditional statement, to look over the different possibilities.

  • So if I have a 90 or a 100 after executing lines seven, eight,

  • grade should be an A. If I have an 80, it should be a B, a C, a D, and an E,

  • depending on what my scores are.

  • But it seems like every time I'm doing this I'm getting an E.

  • And, again, if you're familiar with switch statements,

  • you might see what the issue is here.

  • And if you're not familiar with switch statements, that's OK.

  • Because switch statements are a little bit strange the first time

  • you use them.

  • But debug50 can help us figure out what is happening here.

  • So first thing we got to do, of course, is we got to set that breakpoint.

  • So I got to figure out where I want to set it.

  • Well, it looks like I might have already set it here at line 11.

  • And that seems like a fair enough place to do it.

  • So let's set our breakpoint there.

  • So our program will not freeze and pop open for us

  • until we get to that point in the code.

  • So we'll use debug50 on the debug program number two.

  • "What percentage of the grade did you get as a number?"

  • So let's say I got 100.

  • And now we're frozen.

  • And notice over here, grade has been set to negative one.

  • There's no value there.

  • But that makes sense, cause we haven't assigned grade equals something yet.

  • Percent is 100 and 10th is 100.

  • So we have the value we're expecting.

  • 10th is 100, which means when we get to line 13, grade A should get triggered.

  • So let's step in one line at a time.

  • All right.

  • So notice that my grade is A. And then it's B.

  • And then it's C. And then it's D. And then it's E. And then if I step over,

  • that's what now gets printed.

  • And that's not what I expect.

  • So it seems like by using debug50 to step slowly

  • through my program, what was happening is

  • I wasn't just triggering the one case that I wanted to hit.

  • I seemed to be hitting all of the different cases.

  • And the grade kept changing.

  • It started out at the right thing.

  • It started out as A. And then it became B, and a C, and a D, and an E.

  • And the reason for that, and again, we'll cover this on our video

  • on conditionals if you haven't seen it already,

  • is that at the end of every case option for a switch I needed to have a break.

  • I only ever want one of these things to be true.

  • Now, it's true that you might end up in a situation

  • where you actually want the behavior of falling through the cases,

  • as it's known.

  • But that's not what I want here.

  • I want explicitly to be assigned one value.

  • And then I don't want to look at the rest of the options.

  • So what happened here is I just fell through.

  • I kept executing every line of code from case 100 down.

  • If I had started out at 80, it would have given me a B, and then

  • a C, and then a D, and then an E. And if I started out at like a 60,

  • it would have given me a D and then an E.

  • So I don't want that.

  • So I have to include break statements at the end of all of my different options

  • within the switch.

  • And if I save this and I recompile it, and I clear my terminal

  • and run it one more time, if I get 100, now I have an A. All right.

  • That's good.

  • If I get an 80, I have a B, and so on.

  • And so, again, by using the tools this time

  • of seeing that I was hitting all of these different lines of code,

  • not necessarily that variables were changing--

  • although it was useful to see that A was turning into B

  • and turning into C. What was more useful for me there anyway was seeing

  • that I was hitting all of these lines of code

  • that I shouldn't have been hitting.

  • I should have only been hitting the very one, which

  • was case 90, colon, case 100 colon.

  • Because that was what I had typed in, a 90 or a 100.

  • So it was strange that I ended up falling through.

  • And being able to see it go line by line,

  • as opposed to just the program running so quickly because it's so short,

  • that was a good clue for me.

  • We have one more buggy program.

  • And let's take a look at that one and see if debug50 can

  • help us figure that one out as well.

  • So I'll close this code window here.

  • And let's run debug3.

  • How many stars?

  • Five.

  • Give me six.

  • How many stars?

  • Zero.

  • it gives me one.

  • How many stars?

  • 40.

  • Well, I'm not going to count that, but it's 41 is what it is.

  • So I'm getting a few too many stars.

  • But if I look at my debug3 source code, I'm going from zero to x,

  • and I'm printing out a star for every time.

  • So it seems like that should be working just fine, but it's not.

  • So maybe the debugger can help us figure this out a little bit more cleanly.

  • So let's pop it open.

  • Let's first set a breakpoint.

  • It seems like the integer part is maybe not working.

  • So instead of setting it to breakpoint after that,

  • maybe it somehow is turning five into six?

  • I don't know.

  • Let's set our breakpoint before that.

  • Let's just set our breakpoint right at main.

  • And there was a breakpoint here.

  • We'll just get rid of it.

  • You can double click on a breakpoint to make it go away if you

  • don't want to use that one anymore.

  • And you can also set multiple breakpoints.

  • We're not doing it in these examples.

  • But I could set a breakpoint at first spot,

  • and then maybe another one a little bit later on.

  • It would stop at that point as well.

  • All right.

  • So let's try and compile this.

  • So really quickly recompile.

  • And then we'll run debug50 to take a look

  • at what's happening in this program.

  • All right.

  • How many stars?

  • So, again, we broke at main.

  • So it's going to freeze at line six and wait.

  • If I step over this line, it will print out how many stars.

  • Let's say that I want five.

  • Then we'll step over this.

  • Because we don't need to step in to get in presumably.

  • And when we get through, I's value is 32,677, which is actually OK.

  • It hasn't been set yet, because line nine has not executed.

  • But x is five.

  • It didn't somehow transform into six.

  • So what I now know at least is that my error somewhere

  • happens from line nine down.

  • It's not line six.

  • It's not line seven.

  • It's got to be after that, because x has the correct value.

  • It has five.

  • It didn't somehow get transformed into six.

  • But I's value is 32,767.

  • This is a red herring.

  • This is not a bug.

  • Like I said, line nine has not executed yet.

  • Once line nine executes then I will be set at least to zero,

  • as we'll see right now.

  • So we'll step into this loop.

  • Notice now I is zero, which is what we expect.

  • Then it will print a star.

  • I'm going to step over that, because I don't want to step into printf.

  • So we'll step over.

  • Notice that it printed one star to the terminal.

  • Step again.

  • I is now one.

  • That's what we expect.

  • We went through one iteration of the loop.

  • I incremented by one.

  • I'm going to step over.

  • Print.

  • OK.

  • Two.

  • Three.

  • Four.

  • Now, at this point I should be breaking, right.

  • I'm going from I is equal to zero to I is less than or equal to x.

  • Uh-oh.

  • I see my bug now already, right.

  • I'm counting I is equal to zero to I is less than or equal to x.

  • So I saw it even before debug50 saw it for me.

  • But it's true if I step into this loop, now I's value is five.

  • So it should have stopped if I did what I intended, which is I is less than x.

  • But it actually went into the loop, which

  • means it's going to execute this line of code again.

  • And now it's true that if I step into this, I goes away, right.

  • Because if I became six, this loop would no longer run.

  • So it goes away.

  • And I break out of the loop.

  • And I jump down to line 12.

  • But I've printed out six stars instead of five.

  • Now, again, these examples are a little bit contrived

  • for the purposes of showing you how to use the debugger.

  • It's not supposed to necessarily find the bug for you.

  • But it's supposed to slow the computer down enough that you

  • can see the steps that it's doing.

  • So the values on the right, being able to track what values variables

  • have is useful.

  • Also I didn't show this, but you can actually change the value of variables

  • if you want.

  • I could say x is equal to 23.

  • I could do this in the middle of my program running,

  • between doing different lines to change things,

  • to see if the behavior is affected in any way.

  • It wouldn't have been that useful here because I've already

  • broken out of the loop.

  • But if I wanted to somehow make it artificially print more and more

  • because I haven't figured it out yet, I can do that.

  • You can do that with any local variable there as well.

  • You can use this to inspect strings and arrays as well,

  • which we're not going to get into here, because this is just

  • supposed to be a general tutorial.

  • But, again, the goal is not so much to be, here's the bug.

  • It's to slow things down enough that you can see exactly what the computer is

  • doing, and see if at any point it deviates

  • from what you expect it to be doing.

  • And that's what all these debugging tools are used for,

  • particularly this GDB based one called debug50.

  • But eprintf.

  • Make sure that your program is printing out

  • sort of sanity check messages in the right spot.

  • help50 is supposed to give you some clues about where

  • you might have compile time errors.

  • And debug50 is supposed to help you figure out

  • where your runtime errors are.

  • So use all these tools in conjunction, and you'll

  • be well on your way to debugging code like an expert in no time.

  • I'm Doug Lloyd.

  • This is CS50.

DOUG LLOYD: So if you're anything like me, when you write code

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋

A2 初級

調試 (Debugging)

  • 2 0
    林宜悉 發佈於 2021 年 01 月 14 日
影片單字