When
you use debugging, you can stop your code during execution and inspect
it. Visual Studio provides a sophisticated Debugger that allows you to
Control the execution of your code so that you can peek inside your code while it's running.
Test your code while you're designing it.
View the data used by your code.
Get detailed information about exceptions that occur.
1. Enabling debugging
To use the Visual Studio
Debugger with your code, you must build your code by using the Debug
build configuration. The Debug build configuration tells the compiler
to create a program database (PDB) file for your code. The PDB file
stores the data about your source code, such as
Source code line numbers
Variable names
Method names
The Visual Studio Debugger uses the PDB file to know how to access your source code while it's being executed.
NOTE
The data stored in the PDB are symbols.
You should generate PDB
files for all builds, including release builds, so that you can debug
the build, even if you didn't build it as a debug build.
|
|
To set your application to
use the Debug build configuration, choose Debug from the Solution
Configurations drop-down list on the Standard toolbar.
2. Firing up the Debugger
Your application has
two modes in the Debugger: executing or breaking. While your
application is executing, everything's A-okay. After your application
stops executing, or breaks, then you get busy with the Debugger.
Your application executes until it encounters either of the following:
While your code is in break mode, you have the features of the Debugger at your disposal for examining your code.
2.1. Controlling execution
One of the primary
features of the Visual Studio Debugger is the ability to control your
program's execution. Controlling execution allows you to walk through
your code, as well as check the values of variables and data.
The Debugger provides the following code execution options:
Starting: This starts your code. You must use the Debug build configuration for the Debugger to fire up.
Stepping: This allows you to step through your code.
Breaking:
You can break the code's execution by setting a breakpoint or by
manually breaking. Your code breaks automatically when an unhandled
exception occurs.
Stopping: Execution stops when your program completes execution or you manually stop it.
You have several ways to start the Debugger:
Debug menu: From here, choose Start Debug, Step Into, or Step Over to execute your code.
Run to Cursor:
Right-click an executable line of code and choose Run to Cursor from
the shortcut menu. The Debugger starts your code and breaks at the line
where your cursor sits.
Keyboard shortcuts: Table 1 lists common keyboard shortcuts you can use to control the Debugger.
You can use the keyboard shortcuts almost exclusively to step through code.
|
|
Debug toolbar: The Debug toolbar acts like standard VCR buttons for controlling your code's execution. Figure 1 shows the Debug toolbar.
Table 1. Common Debugging Keyboard Shortcuts
Keyboard Shortcut | Command |
---|
F5 | Start Debugging |
Ctrl+F5 | Start without Debugging |
F11 | Step Into |
F10 | Step Over |
Shift+F11 | Step Out |
2.2. Breaking execution
The first step in using the
Debugger is breaking your code during execution. To break your code
during execution, you can do any one of the following:
In most cases, you'll likely set
a breakpoint in your code before you start execution. By setting a
breakpoint, your code stops executing at the line of code where the
breakpoint is set. You can then step through the code and watch your
variables while the code executes.
Here's how to set a breakpoint:
Go to the line of source code in the Code Editor where you want code execution to break.
From the Debug menu, choose Toggle Breakpoint.
A solid glyph (red circle) appears in the Code Editor's left gutter. The breakpoint appears in the Breakpoints window. Figure 2 shows the breakpoint.
You can use alternative ways to set breakpoints, such as the following:
You can use the Breakpoints window to manage your breakpoints. From here, you can
Create new breakpoints.
Enable or disable breakpoints.
Set conditions on when the breakpoint occurs.
Filter the breakpoint for specific machines, processes, and threads.
Specify how many times the code should execute before execution breaks.
Here's how to create a new breakpoint via the Breakpoints window:
Press Ctrl+Alt+B to display the Breakpoints window.
Choose New=>Break at Function.
The New Breakpoint window appears.
In the Function text box, type the name of the function where you want to create the breakpoint.
For example, type SayHello() to create a breakpoint at a function called SayHello().
Click OK.
The function appears in the Breakpoints window, as shown in Figure 3.
2.3. Stepping through code
Visual Studio provides
several options for controlling the execution of your code. Besides
just starting, pausing, and stopping code execution, you can step
through your code one statement at a time. The three step options are
Step Into: Breaks on each line of code
Step Over: Breaks on each line of code except functions
The function executes, and code execution breaks at the first line outside the function.
Step Out: Resumes execution on a function and then breaks at the first line of code outside the function
Step Into and Step Over start
the Debugger at the next line of code. Step Out allows you to stop
debugging a function but then break execution as soon as the function
exits.
To step through your code, follow these steps:
Set breakpoints in your code.
For example, create a form with a button and add a Click event for the button. Set the breakpoint on the button's Click event to break the code's execution when you click the button.
Press F5 to start the Debugger.
Visual Studio builds your code and starts execution. The code executes until it encounters a breakpoint. Figure 4 shows an example of the Debugger hitting a breakpoint. The Code Editor highlights the code in yellow.
Press F11 to step into the next line of execution.
Continue to press F11 until you encounter a function.
Step into: To follow the execution into the function, press F11 to step into the function.
Step over: To execute the function without stepping through it, press F10 to step over the function.
Step out: To step out of the function after you enter it, press Shift+F11.
Figure 5 shows an example of the Debugger stepping into a function. The Debugger hit the breakpoint in line 25 in Figure 5. Press F11 to step through each line. At line 25 is the function SayHello(). Step into the function, and the Debugger jumps to line 26 , where the next statement to execute exists. The arrow in the Code Editor's left gutter shows the current line being executed.
Press Shift+F11 to step out of the function.
The Debugger executes the function and returns to the calling line of code.
In the case of the code in Figure 5, pressing Shift + F11 returns you to line 53.
Resume stepping through the code by pressing F11.
F5 is the shortcut key for the
Continue command. Press F5 at any time to resume execution until the
code terminates or hits another breakpoint.
|
|
The Debug toolbar has three buttons that correspond to the Step Into, Step Over, and Step Out commands, respectively. Refer to Figure 1.
You can use the Run to Cursor
command to execute your code to the cursor. Just right-click a line of
code in the Code Editor and then choose Run to Cursor from the shortcut
menu. Code execution breaks at the line where your cursor is positioned.
To know whether your code is running or debugging, look for Running or Debugging, respectively, in the title bar. Figure 7-10 shows an example.
2.4. Viewing data with the Debugger
The Visual Studio
Debugger provides several windows for managing debugging. By default,
these windows automatically appear in the bottom of the screen while
you're debugging. You can access and open debugging windows by choosing
the Debug=>Windows menu selection. Table 2 lists the debugging windows and their functions.
Table 2. Debugging Windows and Their Functions
Window | Type | Access | Shortcut Key | Function |
---|
Breakpoints | Execution control | Debug menu | Ctrl+Alt+B | Creates a new breakpoint or edits an existing breakpoint |
Output | Feedback | Debug menu | N/A | Displays results or feedback |
Script | N/A | Debug menu | Ctrl+Alt+N | Lists scripts used by your Explorer program |
Watch | Variable | Debug menu | Ctrl+Alt+W, 1 | Displays variables and expressions you add to the window |
Autos | Variable | Debug menu | Ctrl+Alt+V, A | Displays variables used in the current and preceding lines of code |
Locals | Variable | Debug menu | Ctrl+Alt+V, L | Displays all variables in scope |
Immediate | Variable | Debug menu | Ctrl+Alt+I | Executes commands and sets variable values |
Call Stack | Memory | Debug menu | Ctrl+Alt+C | Displays functions in memory |
Threads | CPU | Debug menu | Ctrl+Alt+H | Displays a set of instructions being executed by your program |
Modules | Memory | Debug menu | Ctrl+Alt+U | Lists the software modules used by your program |
Processes | Memory | Debug menu | Ctrl+Alt+Z | Displays processes which your program has launched or attached to |
Memory | Memory | Debug menu | Ctrl+Alt+M, 1 | Displays contents of memory |
Disassembly | CPU | Debug menu | Ctrl+Alt+D | Displays assembly code of your program |
Registers | CPU | Debug menu | Ctrl+Alt+G | Displays registers' contents |
QuickWatch | Variable | Debug menu | Ctrl+Alt+Q | Displays values of current in break mode value or expression |
Exception | Feedback | N/A | N/A | Displays information about an Assistant exception when an exception occurs |
DataTips | Variable | Hover mouse over variable | N/A | Displays value of variable in scope |
Figure 7 shows the tabs of the debugging windows at the bottom of a screen. Click a tab to access the window.
Many of the debugging windows allow you to observe the contents of your variables and data structures.
Visual Studio offers the
DataTips feature that allows you to view the contents of a variable.
Simply hover your mouse over a variable that's active, and a DataTip
appears that displays the variable's value. Figure 8 shows a DataTip. Notice that you can click the down arrow next to a DataTip and choose a different visualizer. Visualizers display data in different forms to make it easier to read and interpret.
The variable in Figure 8 is a string variable. You can use DataTips to display complex variables, such as DataSets.
Visual Studio also
provides the Autos, Locals, and Watch windows for viewing variable
values. The Autos and Locals windows populate automatically. You use
the Watch window to identify a specific variable that you want to
monitor.
To use the Watch window to monitor a DataSet, follow these steps:
Set a breakpoint in your code where you wish to monitor a variable.
Press F5 to start the Debugger.
When code execution breaks, choose Debug=>Windows=>Watch 1.
The Watch window appears.
NOTE
The Debugger must be in
break mode to open the Watch window. Four Watch windows are available,
and each window has a number from 1 to 4 appended to its Watch name.
Right-click the object that you want to add to the Watch window.
Choose Expression=>Add Watch from the shortcut menu.
The object appears in the Watch window.
NOTE
Be sure to click the object — not a property of the object.
Press F5 to resume execution.
The code executes until it hits a breakpoint.
When the variable or object is in scope (part of the currently executing code), its values appear in the Watch window, as you can see in Figure 9.
You can add objects to the Watch window by typing their names in the Name field. For example, to add a Watch using a DataSet with the name ds
Open the Watch window (using the preceding steps).
Type ds in the Name field.
IntelliSense lists the properties and methods that you can select.
Select a member of the DataSet to watch.
Figure 10 shows the Watch window with DataSet members added.
3. Exception handling in native C++ applications
Structure exception handling
isn't limited to only applications built on the .NET framework. You can
also take advantage of structured exception handling and the powerful
Visual Studio debugger for your native C++ applications. Many C++
libraries that are built into Visual Studio provide structured
exceptions. Some common exceptions provided by built-in libraries
appear in Table 3.
Table 3. Native C++ Exception Classes
Exception Class | Library | Purpose |
---|
std::exception | Standard Template Library (STL) | Base class for all STL exceptions |
std::bad_alloc | Standard Template Library (STL) | Thrown when an STL function can't allocate required memory |
CAtlException | Active Template Library (ATL) | Base class for all ATL exceptions |
CException | Microsoft Foundation Classes (MFC) | Base class for all MFC exceptions |
CMemoryException | Microsoft Foundation Classes (MFC) | Out-of-memory exception |
CFileException | Microsoft Foundation Classes (MFC) | File exceptions |
Consider the simple console application code in Figure 11 that attempts to open a file and output the contents to the console window.
In the code in Figure 11, the file foo.txt doesn't exist, so the code flows into the structured exception handler in the catch() block. As you can see, the Visual Studio debugger provides you the same features as it does for debugging .NET applications. Figure 12 shows an example of debugging a native C++ application.
4. Debugging for those special circumstances
The Visual Studio Debugger is
sophisticated, and you can use it to debug very complex scenarios.
Using the Debugger in a single-tier Windows application is about as
easy as it gets. In the real world, however, applications aren't quite
that simple.
You can use the Visual Studio Debugger to debug any of these items:
NOTE
Going through the
setup processes for each of these is beyond the scope of this book. See
the Visual Studio documentation for more information.
After you get the Debugger set up to work in your scenario, controlling execution and watching variables are basically the same.
5. Debugging generated code
Visual Studio generates a lot
of code for you. Sometimes, you'll want to step through that code with
the Debugger so you can see how the code works. To step into code that
is not yours, however, you must disable the Debugger's Just My Code
feature.
To disable the feature, follow these steps:
Choose Tools=>Options.
The Options window appears.
Clear the Enable Just My Code check box.
Now, you can hit
breakpoints inside generated code. To see generated code, click the
Show All Files button on the Solution Explorer toolbar.