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.
