Lab 1 (Xtra): How to use the Debugger


The Idea

The idea of having a debugger is so that debugging would be easier, hence the name debugger. The reason that the debugger is so helpful is that it will show you a "snapshot" of what the memory looks like at any given instance of the execution.  So what happens is that the compiler is going to run your program like a puppet and keep a check on all resources given to the program.  You can setup breakpoints in the program to tell the compiler when to pause the program and show the snapshot of the memory.  This usually will give you a very good idea of what is going on in your program and why it could be not working.


The Visual Studio Interface

To start debugging you must first enter debug mode. To do that you simply press F5. But the problem when you do that is that it just zips through the whole program and leaves you feeling dumb... So what we need to do is setup a breakpoint when you want it to pause, right? Setting up a breakpoint is F9... but you know what? It's kind of gay when you have no example, so let's work with one:

#include <iostream>

using namespace std;

int factorial(int n);

int main()
{

int a = 5;
int result = factorial(a);
cout << result << endl;
return 0;

}

int factorial(int n)
{

if (n == 1)
  return 1;
int res = factorial(n-1)*n;
return res;

}

Ok, so now bring your cursor to the line in the factorial function that says int res = ... Now press F9.

Now you should see a red dot next to that line of code. That red dot signifies a breakpoint like below:

Now that we can actually have the debugger pause somewhere so that it doesn't just blow us off in the dust we can start to debug for real! Now let's press F5. The following should be what you get:

The layout should be what you see. I think each box is very self explanatory. If you don't see all of them then you need to bring them out by going into Debug->Windows->(whichever one you need).

Locals: The locals are all your local variable. Only the variables in the current function (where your yellow arrow is pointing) will show up in this dialog. It shows you the current values of all variables and the type that they are. The Auto tab is just what Visual Studio thinks is the best stuff. The Watch1 is a place that you can do some simple calculations with your local variables, almost totally useless.

Call Stack: This is a list of all functions called during execution until that time. This will list all the function calls with their parameters that have a "=" sign between the parameter name and the actual parameter value when it was passed in.

The yellow arrow: The yellow arrow indicates where in your code the run is at. It says absolutely nothing about recursive calls or nested functions or anything else at all. It just tells you what line is the next line that will be executed. REMEMBER: the yellow arrow points at the line that is AFTER your currently executed line. You can also leave your mouse over a variable for a few seconds to bring up their current value.

Basic controls: These things are as self explanatory as it gets except the last button. The last button is to restart the debug. It brings your current line to the first line and breaks there.

During debug it is good to use some shortcut keys:

F5: Continue - it gets the program running again and won't stop until it comes to a breakpoint again

F9: Set/Clear Breakpoint - it just sets a breakpoint if there isn't one or clears one if there is one

Ctrl+Shift+F9: Clear all Breakpoint

F10: Step Over - If you are in paused mode it just steps forward 1 line (or 1 line that it can)

F11: Step Into - If you are over a function call you can bring the current location into that funciton that's been called.

There are more functionalities than this but at this point I'd like to have you guys explore on your own. This is an invaluable tool that makes life easier for both you and I.


Exercise

Trace this program:

#include <iostream>
using namespace std;

int pow(int a, int b);

int main()
{
      int temp = 5; 
      int result = pow(temp,5); 
      cout << result << endl; 
      return 0;
}

int pow(int a, int b)

      if (b==0) 
            return 1; 
      int res = a*pow(a, b-1); 
      return res;
}