Chapter 9: Basic Debugging

Quiz Solutions

Solution to Question 9-1. The simplest way to set a breakpoint is to go to the line where you want execution to stop, and click in the left margin. A red dot will appear on the line.

Solution to Question 9-2. When the execution stops, the breakpoint will have a yellow arrow pointing to the highlighted line of code.

Solution to Question 9-3. Pressing F10 steps over a method; pressing F11 steps into the method.

Solution to Question 9-4. Right-clicking on the line where the breakpoint is set opens a context menu that allows you to disable the breakpoint, or to set conditions on the breakpoint (in Visual Studio only).

Solution to Question 9-5. The Locals window shows all the variables that are in scope at the breakpoint. The Autos window shows variables used in the current and previous statement.

Solution to Question 9-6. In the Locals window (and the Autos window as well), objects that have internal state appear with a + sign next to them. Clicking the plus sign expands the object so that you can view its internal state.

Solution to Question 9-7. The easiest way to set a watch on a variable is by either right-clicking on the variable and choosing “Add to Watch window,” or by clicking and dragging the variable directly onto the Watch window.

Solution to Question 9-8. To open a QuickWatch window, you right-click on the variable and choose QuickWatch, or select Debug → QuickWatch (in Visual Studio only).

Solution to Question 9-9. The call stack shows which method called the current method, and which method called that method, and so forth. This allows you to determine the exact path your code followed to bring you to the current method.

Solution to Question 9-10. In the Call Stack window, simply click on a method call and you’ll be taken to that point in your code.

Exercise Solutions

Solution to Exercise 9-1. You’ll use the following program for this exercise. Either type it into Visual Studio, or copy it from this book’s website. 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;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_9_1
{
     class Tester
    {
        public void Run(  )
        {
            int myInt = 42;
            float myFloat = 9.685f;
            Console.WriteLine("Before starting: 
 value of myInt:
                    {0} 
 value of myFloat: {1}", myInt, myFloat);
            // pass the variables by reference
            Multiply( ref myInt, ref myFloat );
            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(  );
         }
    }
}
  1. Place a breakpoint in Run( ) on the following line, and then run the program:

    Console.WriteLine("Before starting: 
     value of myInt:
                 {0} 
     value of myFloat: {1}", myInt, myFloat);

    What are the values of myInt and myFloat at the breakpoint?

  2. Step into the Multiply( ) method, up to the call to Divide( ). What are the values of theInt and theFloat at this point?

  3. Stop debugging, 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?

  4. 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?

The solutions to these tasks are as follows:

  1. As shown in the Locals window, myInt is 42 and myFloat is 9.685, because both have just been set.

  2. theInt is 84 and theFloat is 19.37.

  3. The value of myInt doesn’t change until control returns to Run( ), after the Multiply( ) method has finished.

  4. There are five calls in the call stack at this point: Main( ), Run( ), Multiply( ), Divide( ), and Add( ).

Solution to Exercise 9-2. 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 website:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_9_2
{
    class Tester
    {
        public void Run(  )
        {
            int myInt = 42;
            float myFloat = 9.685f;
            Console.WriteLine("Before starting: 
 value of myInt:
                    {0} 
 value of myFloat: {1}", myInt, myFloat);
            // pass the variables by reference
            Multiply( ref myInt, ref myFloat );
            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 whether 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.

Solution to Exercise 9-3. Type the following program into Visual Studio, or download it from the book’s website:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Exercise_9_3
{
    class Program
    {
        public static int Factorial(int myInt)
        {
            int result = 1;
            for (int i = 1; i < myInt; i++)
            {
                result = result * i;
            }
            return result;
        }

        static void Main(  )
        {
            int input = 5;
            Console.WriteLine("{0} factorial is {1}",
                               input, Factorial(input) );
        }
    }
}

This program is supposed to take the factorial of the value of input, except it’s not working properly. (The factorial of n is the product of all the positive integers less than or equal to n. So, the factorial of 5 is 5 x 4 x 3 x 2 x 1=120.) Find the error and resolve it.

When you run the program, you’ll see that instead of calculating the factorial of 5 as 120, this program calculates it as 24. If you set a breakpoint on the line where Factorial( ) is called and step through the method, you’ll see that in the loop, i never reaches the value of 5, so the loop ends and the result is wrong. There are a few ways to fix this, but the easiest is to change the condition in the for loop from i < myInt to i <= myInt.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.244.40