Go to the line where you want execution to stop, and click in the margin. A red dot will appear on the line.
Pressing F10 steps over a method; F11 steps into the method.
Right-click on the line and choose breakpoints and then disable breakpoint, or right-click on the breakpoint and choose disable.
The Locals window shows all the variables that are in scope. The Autos window shows variables used in the current and previous statement.
Either right-click on the variable and choose “Add to Watch window” or just click and drag the variable directly onto the Watch window.
Right-click on the variable and choose “QuickWatch,” or select Debug → QuickWatch.
The call stack shows which method called the current method, and which method called that method, etc. This allows you to determine the exact path your code followed to bring you to the current method.
You’ll use the following program for this exercise. Either type it into Visual Studio, or copy it from this book’s web site. Note that this is spaghetti code—you’d never write method calls like this, but that’s why this is the debugging chapter.
using System; namespace Debugging { class Tester { public void Run( ) { int myInt = 42; float myFloat = 9.685f; System.Console.WriteLine("Before staring: value of myInt: {0} value of myFloat: {1}", myInt, myFloat); // pass the variables by reference Multiply( ref myInt, ref myFloat ); System.Console.WriteLine("After finishing: value of myInt: {0} value of myFloat: {1}", myInt, myFloat); } private static void Multiply (ref int theInt, ref float theFloat) { theInt = theInt * 2; theFloat = theFloat *2; Divide( ref theInt, ref theFloat); } private static void Divide (ref int theInt, ref float theFloat) { theInt = theInt / 3; theFloat = theFloat / 3; Add(ref theInt, ref theFloat); } public static void Add(ref int theInt, ref float theFloat) { theInt = theInt + theInt; theFloat = theFloat + theFloat; } static void Main( ) { Tester t = new Tester( ); t.Run( ); } } }
Place a breakpoint in Run( )
on the following line:
System.Console.WriteLine("Before staring: value of myInt: {0} value of myFloat: {1}", myInt, myFloat);
Step into the Multiply( )
method, up to the call to Divide( )
. What are the values of
theInt
and theFloat
at this point?
Run the program again, and when it reaches the
breakpoint in Run( )
, set
a watch on myInt
. Step
through the methods. When does the value of myInt
change?
Set another breakpoint in Add( )
at this line:
theInt = theInt + theInt;
Run the program. How many calls are in the call stack when the program reaches this breakpoint?
Answers:
As shown in the Locals window, myInt
is 42 and myFloat
is 9.685, because both
have just been set.
Use theInt
is 84
and theFloat
is
19.37.
The value of myInt
doesn’t change until control returns to Run( )
, after the Multiply( )
method has
finished.
There are five calls in the call stack at this point:
Main( )
, Run( )
, Multiply( )
, Divide( )
, and Add( )
.
The program in this exercise is similar to the first, but it has a logic error. Type this program into Visual Studio or download it from this book’s web site.
using System; namespace Debugging { class Tester { public void Run( ) { int myInt = 42; float myFloat = 9.685f; System.Console.WriteLine("Before staring: value of myInt: {0} value of myFloat: {1}", myInt, myFloat); // pass the variables by reference Multiply( ref myInt, ref myFloat ); System.Console.WriteLine("After finishing: value of myInt: {0} value of myFloat: {1}", myInt, myFloat); } private static void Multiply (ref int theInt, ref float theFloat) { theInt = theInt * 2; theFloat = theFloat *2; Divide( ref theInt, ref theFloat); } private static void Divide (ref int theInt, ref float theFloat) { theInt = theInt * 3; theFloat = theFloat * 3; Add(ref theInt, ref theFloat); } public static void Add(ref int theInt, ref float theFloat) { theInt = theInt - theInt; theFloat = theFloat - theFloat; } static void Main( ) { Tester t = new Tester( ); t.Run( ); } } }
If you run this program, you will not get the same results as you did in the previous example. Use the debugging tools you just learned about to find the error. Correct the error, and then run the program again to see if the results are correct.
You could find this error by setting a breakpoint on the call to
Run( )
, and stepping through the
code from there, watching the values of theInt
and theFloat
. You could also find it by setting
breakpoints on each of the method calls and examining the values of
theInt
and theFloat
each time.
The first errors you’ll probably find are these in Divide( )
:
theInt = theInt * 3; theFloat = theFloat * 3;
theInt
and theFloat
are multiplied by 3, not divided.
However, if you fix these errors and run the program, the result is
still 0 for both variables. That’s because there are two more errors
in Add( )
:
theInt = theInt - theInt; theFloat = theFloat - theFloat;
As you can see, the programmer isn’t a very good typist—the variables are subtracted instead of added. If you fix these errors, the program will run as expected.