To most seasoned programmers, there is only one type of bug that ever exists in a program. This bug is the most aggravating thing that could ever happen. It is when the requirements that were given to you are wrong or the client simply changed his mind. All other bugs are simply "features of the application" that are misunderstood to everyone but the person who programmed the logic. In the following section, you will learn about the different tools that the Visual Studio .NET environment gives you to find these misunderstood features.
Setting Up the Application for Debugging
Before you can debug an application, it is important to understand the different configurations that Visual Studio .NET offers you for your application. Table 42.1 provides a list of the choices.
In Visual Studio .NET, there are several ways to do just about everything and switching from Debug to Release mode is no exception. Figure 42.1 shows the quick way to change from Debug to Release mode. Just select the drop-down list and choose the configuration that you want to use.
Figure 42.1. You can choose the active build configuration you want very quickly with this option.
You can edit the build configurations, but you cannot change the active build configuration by right-clicking the project and selecting the Properties menu option. This will bring up the Project Properties dialog, as shown in Figure 42.2.
Figure 42.2. You can edit the different build configurations from the Project Properties dialog.
In addition to the methods just described, you can open the Configuration Manager dialog shown in Figure 42.3.
Figure 42.3. You can choose the build configuration you want from the Configuration Manager.
From here, you can select the active build configuration, create your own custom configurations, or edit an existing one, as shown in Figure 42.4.
Figure 42.4. You can create your own custom configurations using Configuration Manager.
Although you can debug an application without debug information (the Generate Debugging Information setting turned off), your debugging capabilities will be severely limited. To properly debug an application, it is necessary to generate the debugging information. This allows the debugger to insert the variable names and other helpful information.
Understanding Syntax and Error Messages
A syntax error is a bug, or error, that prevents the compiler from completing its job. Visual Studio .NET looks at and checks for some syntax errors while you are typing. When Visual Studio .NET encounters one of these syntax errors, it displays a squiggly line where the syntax error occurred, as shown in Figure 42.5, and adds the error to the Task List, as in Figure 42.6.
Figure 42.5. As indicated by the squiggly line, you can see where the syntax error occurs in the code view.
Figure 42.6. You can view all encountered syntax errors in the Task List.
When the compiler encounters a syntax error, it adds an error message to the Task List, as in Figure 42.6, and the Output window, shown in Figure 42.7.
Figure 42.7. You can also see the syntax errors in the Output window.
When reviewing the Output window or Task List, if you want to quickly go to the line that generated the error, you can simply double-click on the error and Visual Studio .NET will place your cursor on the offending line of code, as shown in Figure 42.8.
Figure 42.8. Double-clicking on the error brings you to the offending line of code.
Understanding the Debugging Tool Windows
As with everything in Visual Studio .NET, there are tool windows for just about everything that must be displayed. In addition to the code window, Visual Studio .NET provides 12 tool windows just for debugging purposes. This section will list each of these windows and give a short description of each. Most of these windows will be used and explained later in this chapter.
Using the Autos Window
The Autos window displays all the variables for both the current and previous statements. In addition, it will display any return values for a method as well as values returned from methods that were called from that method. Figure 42.9 shows the Autos window.
Figure 42.9. The Autos tool window.
Using the Locals Window
The Locals window displays local variables. This window is automatically populated when variables come in scope. The variables are removed when they go out of scope. Figure 42.10 shows the Locals window.
Figure 42.10. The Locals tool window.
Using the Watch Window
The Watch window displays variables that you specify. You can add variables to this window by simply dragging and dropping them into this window. You can also click on an empty space in the window grid and type the name of the variable that you want to add. Figure 42.11 shows a Watch window.
Figure 42.11. The Watch tool window.
Using the This Window
The This window shows the object pointed to by the this pointer. Figure 42.12 shows the This window.
Figure 42.12. The This tool window.
Using the Call Stack Window
The Call Stack window displays the functions on the call stack. Figure 42.13 shows the Call Stack window.
Figure 42.13. The Call Stack tool window.
Using the Threads Window
The Threads window displays information about the Threads that are being used by the application. Figure 42.14 shows the Threads window.
Figure 42.14. The Threads tool window.
Using the Breakpoints Window
The Breakpoints window displays information about all the breakpoints that are set for an application. Figure 42.15 shows the Breakpoints window.
Figure 42.15. The Breakpoints tool window.
Using the Command Window
The Command window enables you to enter commands to take place for the currently running application. For example, if you are in a loop in the current program and the loop variable is i, you could enter the command i=0. This would set the i variable to 0. Figure 42.16 shows the Command window.
Figure 42.16. The Command tool window.
Using the Output Window
In addition to the Output window displaying any compiler errors, it can be used to display trace information or other types of debugging information. Figure 42.17 shows the Output window.
Figure 42.17. The Output tool window.
Using the Modules Window
The Modules window displays information about the modules that are used by your application. Figure 42.18 shows the Modules window.
Figure 42.18. The Modules tool window.
Using the Memory Window
The Memory window displays information about memory used by your application. Figure 42.19 shows the Memory window.
Figure 42.19. The Memory tool window.
Using the Registers Window
The Registers window displays the contents of each register. Figure 42.20 shows the Registers window.
Figure 42.20. The Registers tool window.
Navigating the Application
The ability to navigate through an application while debugging is an essential part of the debugging process. Visual Studio .NET offers several commands for this very purpose. Table 42.2 displays the available commands and a brief description of each one.
Setting and Using Breakpoints
To debug an application, it is often necessary to stop the execution of that application at a certain point. TO do this, Visual Studio .NET offers breakpoints. When the debugger reaches a valid breakpoint, it stops the execution of that program until you resume the application. To set a breakpoint, click in the area to the left of the line of code at which you want to stop execution. Figure 42.21 shows a breakpoint that has been reached by a debugger.
Figure 42.21. A valid breakpoint that has been reached by the debugger.
If you display the Breakpoints window, you will now see the breakpoint that you just set listed in that window. You will also see that it does not have a condition associated with it and it has a hit count of Break Always (Currently 0). To set a condition for this breakpoint, right-click on the breakpoint and select the Properties menu option. This will bring up the Breakpoint Properties dialog shown in Figure 42.22.
Figure 42.22. The Breakpoint Properties dialog.
From the Breakpoint Properties dialog, you can click on either the Condition button to associate a condition, as in Figure 42.23, or the Hit Count button to associate a hit count condition with this breakpoint.
Figure 42.23. Associate a condition with a breakpoint through this dialog.