找回密码
 申请新用户
搜索
热搜: 活动 交友 discuz
查看: 5424|回复: 0

Visual Basic .NET Debugger

[复制链接]
发表于 2008-9-1 15:26:04 | 显示全部楼层 |阅读模式
转自:http://www.cs.uvm.edu/~upe/resources/debugging/visualBasicDebug/

Contents

[size=+1]This Tutorial
This tutorial demonstrates how to use the debugging tools in Visual Studio .NET to find and fix problems in your programs. It is designed for people for who have never used a debugger before, but it may be useful for anyone who hasn't used the debugging tools in this particular software before. You should already have some knowledge of Visual Basic .NET, but the examples used for demonstration purposes are very simple. These tools can be used with programs of any size.

[size=+1]Introduction
Any debugger (whether in Visual Studio, in some other IDE, or a stand-alone program) will provide two basic functions to help you fix your code:
  • Trace Execution: You can execute one line of your program at a time, so you'll be able to see exactly where a problem occurs.
  • Watch Variables: As you trace through your program, you can monitor your variables as they get changed (so you can identify the source of bad data right away).
A variety of tools are available in Visual Studio to help you accomplish these two things (and perhaps a few more that are more subtle). We'll start by looking at the most essential tools.

[size=+1]Types of Errors
Before we begin, it's important to distinguish between two different types of errors you can have in a program. Visual Studio's compiler identifies some problems as soon as you try to run your program, and presents these in the "Output" window at the bottom of the screen:

[size=-1]A Compiler Error

These errors are almost always easy to repair. The error shown above can be fixed by declaring the 'z' variable with the appropriate type. The compiler tells you what the problem is and where it occurs in your program, so the only thing you need to know is what you had in mind when you wrote that statement.

The second type of error is the kind that appears while your program is running. You may get an exception that identifies a specific problem (such as "Subscript out of Bounds") or you may just see something that isn't working the way you want. Finding these problems can be very tricky, but the debugger lets you see your program in a different way, and that can make even these obscure problems easy to fix.

[size=+1]A Buggy Program
Let's start by looking at a simple program that has a simple bug. Scorpion is a program that's supposed to convert temperatures in Fahrenheit to Celsius (or vice versa). This program "compiles clean" (no errors, no warnings) but it does not behave as expected. Here's an example of what it does:

[size=-1]Sample Runs of Scorpion

Clearly there is something wrong with this program, even though it compiled without any trouble. First, I tried converting 32°F to Celsius (which should be 0°) and got an answer of 14°. Then I tried the conversion the other way -- 0°C to Fahrenheit, but this time got 0° as a result.

The code for Scorpion is below. Start a new VB project and open the code for the blank form that's created for the project. Press Edit > Select All (or Ctrl+A) to highlight ALL the code (including the code that Microsoft creates). Paste the Scorpion code in the window so it replaces all the existing code. Before you can run the program, you'll have to visit the Project Properties page and change the Startup Object to frmCalculator. Try running the program yourself. Even if you can identify a bug just by looking, don't change anything yet. This is a deliberately simple example, but if this small piece of code were part of a larger program these errors may not be as easy to find.

[size=-1]Scorpion.vb [size=-1](Open in new window)

The first thing you should try doing is switching back to the program (using Alt+Tab or the taskbar). All you'll get is a white box! This makes sense, since painting the window may have invoked code (and code isn't allowed to run until you say so when you're debugging), but it's still one of the most annoying traits of the VB debugger. If you're hunting for a problem with visual symptoms, you'll have to find it without seeing the symptoms at the time.

[size=+1]Breakpoints
The first thing we want to do in our general debugging strategy is identify which part of the program we think is responsible for the problem. In event-driven programming it's very hard to find a bug without at least some idea of where it might be caused. Fortunately, there's usually a pretty natural starting point. In this case, we know that clicking the "To Celsius" button performs the conversion, so let's use that as our starting point.

Once you know where you want to start debugging, put a breakpoint there. You can do this by clicking in the gray margin next to a line of code, or pressing F9 while on that line. (Note that there are many ways to activate most debugger functions, but only one or two will be presented here for each command.)

[size=-1]A Breakpoint

The visual effect is obvious: a red dot appears in the margin, and the line is highlighted in red. The meaning is that whenever the program reaches this line of code in the debugger, everything will stop and you'll be able to look at the details.

[size=+1]Starting the Debugger
Visual Studio lets you run your program by pressing Ctrl+F5 (or clicking "Start Without Debugging" in the "Debug" menu), but it treats Debug mode as the default. This may cause some frustration as you start setting up breakpoints (which we'll cover momentarily), so you may want to get in the habit of using Ctrl+F5 unless you specifically want to use the debugger.

Obviously in this case we do want to use the debugger, so press F5 (or click the Start button).

[size=-1]Starting the Debugger

The Scorpion form will appear normally. Enter 32 in the Fahrenheit box again, and click "To Celsius" so we can get to the code we marked. As soon as you click the button, the Visual Studio window comes into the foreground, and the line we marked earlier is now highlighted in yellow (with a yellow arrow in the margin):

[size=-1]The Breakpoint is Hit

This yellow arrow and highlighting indicate which statement will execute next. Commit that to memory, since it's easy to forget when you're looking at a larger piece of code. The statement that is highlighted has not been executed yet, but it will execute next.

[size=+1]Watching Variables
Before we execute that code, we want to make use of the debugger's other primary tool: the ability to look at the contents of variables. The "Autos" window should appear automatically when you start the debugger, but if it doesn't you can access it in the Debug menu. Click Debug > Windows > Autos.

[size=-1]Open the Autos Window

The "Locals" and "Watch" windows are also available from this menu. What the Autos window shows is a list of all the variables you're using in this function:

[size=-1]The Autos Window

It may be tempting to observe that the 'fahrenheit' variable is still 0 and say "Ah ha! There's a problem!" Remember, however, that the line that assigns 'fahrenheit' a value hasn't executed yet! We can see that the value in the textbox is "32" as expected, but there isn't much other information available yet.

Before we continue, it's worth mentioning what the "Locals" and "Watch 1" windows are, since they are highly related. All these windows show the contents of variables; the only difference is what variables they list. The Autos window shows variables that you're currently using. The Locals window shows all variables that are currently in scope, including many that you may not need. Try expanding the "Me" entry in the Locals window and see just how many variables there are!

The "Watch 1" window is a place for you to enter any expression you want to watch. This could be a variable, some simple mathematical expression (like "fahrenheit - 32", which is used in our calculation), or even a function call (like "fahrenheit.Equals(0)"). The other three "Watch" windows work the same way (so you can have four lists of personalized 'watches' at once).

[size=-1]The Locals and Watch Windows

Usually the "Autos" window will contain the information you want, so we'll use that for now. Consider that the default, and use the other two if you need extra information.

[size=+1]Stepping
Now we'd like to execute the statement that's highlighted and see what effects it has. The "Step Over" command will do this, and the easiest way to perform a "Step Over" is by pressing the F10 key. Even if you don't normally use keyboard shortcuts, you will probably find it helpful to be able to concentrate on your code while you're using the debugger, so this particular keyboard shortcut is worth knowing. You can also use the Step Over icon:

[size=-1]Step Over

The yellow arrow advances to the next line, which indicates that the statement is done executing, but also the Autos window updates to reflect the change. The value of 'fahrenheit' is 32, which is what we'd expect:

[size=-1]The fahrenheit Variable has Changed

Notice that the value is in red, indicating that it changed when you executed that line. If you're watching many things at once, this helps you figure out which information is new. Since the result of the statement was what we expected, it's unlikely that there's anything wrong. Let's execute the next statement and see what happens to the variables:

[size=-1]The celsius Variable has Changed

That's definitely not the expected result, so it's worth examining that line in detail. We can even look at its component parts in the Watch window:

[size=-1]Watching Relevant Expressions

From all this information, we should be able to infer (even if it wasn't obvious before) that the statement needs to be changed to  [size=-1]celsius = (fahrenheit - 32) * 5 / 9

[size=+1]Step Into, Step Out
We've already discussed what the "Step Over" button does, but there are two more icons on the debugger toolbar that look quite similar. Their functions are related, so let's discuss them now. When you "Step Over" a statement, the entire statement is executed - including any function calls. What if you want to step into a function and see what happens inside though? That's where you'd use the "Step Into" command.

Step Into

Just like the "Step Over" icon, which shows the arrow leading completely OVER the code, the "Step Into" icon shows an arrow leading INTO the code (relate that logic to what the commands do and it will be easy to remember which icon you want). You can also press F11 to perform a "Step Into."

You should consider "Step Over" the default -- always use that unless you specifically want to examine the innards of a function. Even if you are in the habit of pressing F10, however, you will undoubtedly step into a function by mistake from time to time. The "Step Out" command is the way to remedy that mistake. Performing a "Step Out" tells the debugger to run the current function in its entirety and then stop.

Commit that to memory, since you will undoubtedly need it in time: when you step into a function by mistake, use the "Step Out" command to effectively undo that mistake.

[size=+1]Conditional Breakpoints
Whenever you have a piece of code that runs more than once, it can create a problem for debugging. Suppose, for example, that you have a loop that works for 100 iterations, but then fails for some reason. (This could easily happen if you were processing elements in a large array, for example.) Setting an ordinary breakpoint wouldn't help much, since the breakpoint would be hit every single time through the loop.

Visual Studio lets you set breakpoints conditionally, however, so the program will only stop if a particular condition is met. To give a breakpoint a condition, set the breakpoint normally, then right-click and select "Breakpoint Properties."

Breakpoint Properties

You can make a breakpoint conditional in several ways:
  • You can tell the breakpoint to trigger only after it has been hit n times. This is the "Hit Count" method. Note that this is a count of how many times the breakpoint itself is encountered, so if the breakpoint is inside an 'if' statement, the "Hit Count" may or may not match the number of iterations of the loop.

    You can also tell the program to stop when the hit count is anything above n, or even if it's a multiple of n (so you can check on a loop's progress every 500 iterations, for example.

    Click the "Hit Count" button on the Breakpoint Properties window to change these settings.

    Breakpoint: Hit Count
  • You can tell the breakpoint to stop the program only if some (arbitrary) condition is met. You might do this if there's a particular scenario you're interested in studying (for example, you might want to observe all situations in a loop where some variable is negative).

    From the Breakpoint Properties window, click the "Condition" button and set whatever condition you want:

    Set a Condition
  • If you're interested in stopping whenever some variable (or expression) has changed, you can set a conditional breakpoint in a different way. In the "Breakpoint Condition" window, there are two choices marked "is true" and "has changed." We used the first when we wanted to stop the program only under certain circumstances. The second can be used to monitor a variable.

    If you entered 'someVar' in the "Condition" field, and checked "hasChanged," then the breakpoint would only stop on iterations where the value of 'someVar' is different from when it was last seen. Although conditional breakpoints are most often useful inside loops, there's no reason they must be used inside a loop. This is just one more tool you have available; it may be handy in any number of situations.
[size=+1]Watchpoints / Data-Based Breakpoints
Conditional breakpoints can help you find where a variable gets changed, but only in certain circumstances. The breakpoint is still tied to a single line of code. Visual Studio .NET has a breakpoint that's tied to a variable rather than a line of code (so you'd be able to stop the program whenever that variable changes, regardless of where it happens in the program). Unfortunately, that particular tool is not supported for Visual Basic code, so you'll have to stick to traditional breakpoints for solving your problems.

[size=+1]Summary
Ultimately the debugger just gives you the ability to follow the execution of your code closely, and the ability to watch the contents of variables. Although this example was extremely simplified, exactly the same technique applies to programs of any size.

The Technique:
  • Identify a general part of the program that may be at fault.
  • Set a breakpoint at the beginning of that area.
  • Step through your code one line at a time, and watch any interesting variables for changes.
  • Whenever something unexpected happens, scrutinize that line very closely - there's something wrong!

[size=+1]Practice
The only way you'll really learn the debugger is to use it. Although you'll learn best by debugging your own programs, you may want to start by exploring this simple example. There are two more bugs in the Scorpion program -- one that's substantial, one that may be more subtle. Test the program thoroughly, and use the debugger to find where the problems are.
您需要登录后才可以回帖 登录 | 申请新用户

本版积分规则

守望轩 ( 湘ICP备17013730号-2 )|网站地图

GMT+8, 2024-3-28 16:59 , Processed in 0.075773 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表