VB .NET Chapter 6 Debugging your code

Error Handling and Debugging in VB .NET

Debugging your code is something you will need to do. Unless you write perfect code every time, there's no getting away from it. In this section, we'll take a look at ways you can track down errors using VB.NET.

Types of Error

Programming errors are generally broken down into three types: Design-timeRuntime, andLogic errors.
Design-time error is also known as a syntax error. These occur when the environment you're programming in doesn't understand your code. These are easy to track down in VB.NET, because you get a blue wiggly line pointing them out. If you try to run the programme, you'll get a dialogue box popping up telling you that there were Build errors.
Runtime errors are a lot harder to track down. As their name suggests, these errors occur when the programme is running. They happen when your programme tries to do something it shouldn't be doing. An example is trying to access a file that doesn't exist. Runtime errors usually cause your programme to crash. If and when that happens, you get the blame. After all, you're the programmer, and you should write code to trap runtime errors. If you're trying to open a database in a specific location, and the database has been moved, a Runtime error will occur. It's your job to predict a thing like this, and code accordingly.
Logic errors also occur when the programme is running. They happen when your code doesn't quite behave the way you thought it would. A classic example is creating an infinite loop of the type "Do While x is greater than 10". If x is always going to be greater than 10, then the loop has no way to exit, and just keeps going round and round. Logic errors tend not to crash your programme. But they will ensure that it doesn't work properly.

Design Time Errors in VB .NET

Design time errors, remember, are syntax errors. It's when VB .NET hasn't understood what you have typed. If that isn't clear, a few examples should explain it beter. So do the following:
  • Create a new Windows project
  • Add a button and textbox to your form
  • Leave the Name properties on the defaults of Button1 and Textbox1
  • Double click your button to access its code, and type the following:
Textbox2.Text = "Debug"
When you finish typing the line, VB.NET puts a blue wiggly line under Textbox2:
Notice the blue wiggly line
If you hold your mouse over Textbox2, you'll see a yellow tool tip appear, like the following:
Hold your mouse over Textbox2
The error is occurring because you don't have a textbox called Textbox2. You'll also see this same "Not declared" error if you try to set up a variable on the fly (which you were allowed to do in previous version of VB.) As an example, change your code to this:
strText = "Debug"
TextBox1.Text = strText

Here, we're trying to put the word "Debug" into a variable called strText. We then want to assign this variable to the Text property of Textbox1. However, VB.NET protests about this, and puts a wiggly line under all occurrences of strText:
strText has a blue wiggly line under it
Hold your mouse over the variable strText and you'll see the "not declared" tip again:
strText is not declared
The problem this time is that we haven't declared the variable strText. Change the code to this:
Dim strText As String
strText = "Debug"
TextBox1.Text = strText

Now that we have declared a variable, the wiggly lines will go away. If we added the variable declaration in the wrong place, however, the wiggly lines would come back. Change you code to this:
strText = "Debug"
TextBox1.Text = strText

Dim strText As String
The wiggly lines will be back. That's because the declaration comes on the third line. When VB.NET meets the first two lines, it knows nothing about the strText variable.
If you have the Error List window open, you'll see a report of your error (If you can't see the Task List window, from the menu bars click View > Other Windows > ErrorList in version 2010, or justView > Error List in version 2012.):):
The Task List Window
The description of the error is "Local variable 'strText' cannot be referred to before it is declared". If you double click the icons on the left, VB.NET will highlight the error in your code.
Move the Dim … Line back to the top, and not only do the blue wiggly lines go away, but the Task List will be erased.
Design-time errors like the one above can be quite straightforward to correct. Others can be quite difficult, and you'll see the blue wiggly line but not understand how to correct the error. The Task List should be your first port of call when faced with such an error.

Runtime errors in VB .NET


Runtime errors are a lot harder than Design Time errors to track down. As their name suggests, these errors occur when the programme is running. Runtime errors are the ones that crash your programme. A simple way to crash a programme is to divided by zero. Change the code for your button to this, and try it out:
Dim Num1 As Integer
Dim Num2 As Integer

Num1 = 10
Num2 = 0

TextBox1.Text = CInt(Num1 / Num2)
The CInt( ) part means Convert to an Integer. We're just making sure to convert the answer to the sum into a number. But run your programme and test it out. Click your button and see what happens.
What happens is that you'll get the following error message popping up in Visual Studio Express 2010:
The Overflow Error
In version 2012/13, you'll get the following error message (the 2010 version seems more helpful, and better designed):
Error message in VB NET 2012
Click the Break button, and then stop your programme from running.
When you try to divide by zero, VB.NET throws up the Overflow error message - there would be just too many zeros to go into the Integer variable type. Even if you change the Type into a Singleor a Double, you'd still get the same error message. Programming environments just don't like you dividing a number by zero. If this were in a real programme, chances are it would crash, or "bug out". And you'll get the blame!
If you think the answer to a calculation could result in zero, you should check for this. We'll see how to write code to trap Runtime errors in a moment. But here's another example of one.
From the controls toolbox, add a RichTextBox control to your form. Change the Name property of your RichTextBox to rt1. A RichTextBox is just like a normal textbox but with more functionality. One of these extra functions is the ability to load a file directly. Delete or comment out any code you have for your button, and add the following line:
rt1.LoadFile("C:\test10.txt", RichTextBoxStreamType.PlainText)
However, if you are using Vista or windows 7 then change the file name above to this:
"C:\Users\Owner\Documents\test10.txt"
All the line does is to load (or try to) the text file called "test10.txt" into the RichTextBox. The second argument just specifies that the type of file we want to load is a Plain Text file.
Run your programme, and then click the button. If you don't have a text file called "test10.txt" in the root folder of your C drive, you'll get the following Runtime error message:
The File Not Found error
The additional information is quite useful this time. It's saying that the file "C:\test10.txt" could not be found. If the error occurred in a normal programme, it would shut down. Not something you want a programme to do in mid stream! But let's see how to deal with it.

Try ... Catch in VB .NET


VB.NET has a inbuilt class that deals with errors. The Class is called Exception. When an exception error is found, an Exception object is created. The coding structure VB.NET uses to deal with such Exceptions is called the Try … Catch structure.
In the coding area for your button, type the word Try. Then hit the return key on your keyboard. VB.NET completes the rest of the structure for you:
Try
Catch ex As Exception
End Try
The Try word means "Try to execute this code". The Catch word means "Catch any errors here". The ex is a variable, and the type of variable it is is an Exception object.
Move your line of code from the previous section to the Try part:
Try
rt1.LoadFile("C:\test10.txt", RichTextBoxStreamType.PlainText)
Catch ex As Exception
End Try
When you run your programme, VB will Try to execute any code in the Try part. If everything goes well, then it skips the Catch part. However, if an error occurs, VB.NET jumps straight to Catch. Add the following to your Catch part:
MsgBox(ex.Message)
Your coding window should look like this:
Your coding window
Because ex is an object variable, it now has its own Properties and methods. One of these is the Message property. Run your programme and test it out. Click your button. You should see the following error message:
File Not Found Error
The message is coming from the "additional Information" section of the error message we saw earlier, the one we didn't handle. But the point about this new message box is that it will not crash your programme. You have handled the Exception, and displayed an appropriate message for the user.
If you know the kind of error that a programme might throw, you can get what Type it is from the Error message box you saw earlier. This one:
The File Not Found error
If you have version 2010 of Visual Studio Express, click the View Details links under Actions to see the following:
Details about the error thrown by VB NET
In version 2012/13, you can see the same information in the first line: "An unhandled exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll".
The first line tells us the Type of Exception it is:
System.IO.FileNotFoundException
You can add this directly to the catch part. Previously, you were just catching any error that might be thrown:
Catch ex As Exception
But if you know a "file not found" error might be thrown, you can add that to the Catch line, instead of Exception:
Catch ex As System.IO.FileNotFoundException
You can keep the Exception line as well. (You can have as many Catch parts as you want.) This will Catch any other errors that may occur:
Try
rt1.LoadFile("C:\test10.txt", RichTextBoxStreamType.PlainText)
Catch ex As System.IO.FileNotFoundException
MsgBox(ex.Message)
Catch ex As Exception
MsgBox(ex.Message)
End Try
There is one last part of the Try … Catch Statement that VB.NET doesn't add for you - Finally:
Try
Catch ex As Exception
Finally
End Try
The Finally part is always executed, whether an error occurs or not. You typically add a Finally part to perform any cleanup operations that are needed. For example, you may have opened a file before going into a Try … Catch Statement. If an error occurs, the file will still be open. Whether an error occurs or not, you still need to close the file. You can do that in the Finally part.
But Microsoft advise that you always use Try … Catch Statements in your code. However, throughout the rest of this course, for convenience sake, we won't be using them much. Even when we should be.But that's no excuse for you not to use them!

Logic Errors in VB .NET

The third category of errors are the Logic errors. These can be thought of as coding errors. Your coding errors. They can be quite tricky to track down, and have you tearing your hair out with frustration. You will often hear yourself saying "But that should work! Why won't it!"
Add another button to the form tou created in the first part, and try this code as an example of a logic error:
Dim x As Integer
Dim y As Integer
Dim answer As Integer

x = 10.5
y = 3
answer = x * y
TextBox1.Text = answer

When you've added the code to your button, run your programme and test it out. Before you click the button, what answer did you expect to get?
You'd think that 10.5 multiplied by 3 would give you the answer 31.5. Click your button. The answer that appears in your textbox is 30!
This is a logic error: when you don't get the answer you thought you'd get. The problem, if you were paying attention during the variable types sections, is that we are trying to put floating point numbers into an Integer variable type. The Integer variable only works with whole numbers. When you assign 10.5 to the variable x, the point 5 on the end gets chopped off. So only the 10 gets stored in x. 10 times 3 is thirty, and this is the answer that appears in the textbox.
But the point is that VB.NET did not raise a Design-time error. Nor did it raise a Runtime error. The programme executed, and did not "bug out" on us. It just didn't give you the answer you expected - it was a logic error.
Logic errors can be fairly simple to track down and solve. (The problem above can be solved by changing the variable types from Integer to Single or Double.) But they can also be quite difficult to track down. Especially as your code gets longer and longer. Here's another example of a logic error.
Erase the code you have for button2, and add the following instead:
Dim i As Integer
Dim LetterCount As Integer
Dim strText As String
Dim letter As Char

strText = "Debugging"
For
i = 1 To strText.Length - 1
letter = strText.Substring(1)

If letter = "g" Then
LetterCount = LetterCount + 1
End If
Next
TextBox1.Text = "G appears " & LetterCount & " times"
All the code does is to try and count how many times the letter "g" appears in the word "Debugging". We're using a For loop, and Substring to get one letter at a time. This single letter is then placed inside the variable called letter. An If Statement is used to check if the letter is a "g". If it is, we increment the LetterCount variable. The answer we're expecting in the textbox is 3. Except, we don't get 3. We get zero:
The programme has not found the letter "G"
There were no wiggly lines and therefore no Build errors. When the button was clicked, a Runtime exception did not crash the programme. So that leaves a logic error. But where is it?

Breakpoints and Debugging Tools


In the last part, you added some code to a button. All the code does is try and count how many times the letter "g" appeared in the word "Debugging". We saw that the programme failed to do this, and came up with the answer zero. To help you find out what went wrong, there is a tool in VB .NET called a Breakpoint. Let's see what this is, and how to use Breakpoints.

Breakpoints

A breakpoint is like a note to VB.NET to stop your programme at a particular place. You add one to your code by clicking in the margins. A brown circled then appears, indicating where the code will break. The following two images show how to add one:
Click in the margins to add a Breakpoint
When you click in the margins, to the left of a line of code, a brown circle appears:
A Breakpoint has been added
Notice that the line where you want VB.NET to break is highlighted brown.
Run your programme, and click the button. You are immediately returned to the coding window. The place where you put the Breakpoint will now have a yellow arrow on top of the brown circle. The brown highlighted line will now be yellow:
The Breakpoint is now highlighted in yellow
The yellow highlight indicates where in your code VB.NET is. To continue checking your code, press F10 on your keyboard (you can also press F11, but this will jump into any Subs or Functions you've set up.)
The next line in your code will be highlighted:
The programme has advanced to the next line
The yellow arrow, and the yellow highlight, jump down one line. Press the F10 key again. Then hold you mouse on the letter variable. The value this variable currently holds will be displayed:
Hold your mouse over a variable
The first time round the loop, the value in letter is "e" (The "c" next to it means that the variable type is Character).
If the "e" of "Debugging" is getting checked first, what happened to the "D"? Straight away, this indicates a problem. And the problem is that the Substring method starts counting from zero. So halt your programme by clicking "Debug > Stop Debugging", or click the Stop icon on the toolbar. Change the line in question to this:
letter = strText.Substring(0)
Run your programme again, and click the button. When you are returned to your code, press the F10 key and check the value of the letter variable. It should now be this:
Hold your mouse over the variable again
This time, the code is catching the first letter of the word when the loop begins, and not the second one.
Is that it? Have we found the cause of our problems? Stop your programme. Click on the brown circle to get rid of the Breakpoint. Run it again, and see what happens.
The number of G's counted is still zero! So the logic error has not yet been tracked down. Create another Breakpoint at the same place, and try again.
You can continue pressing the F10 key until you've spotted the error. Or you can use another debugging tool - the Locals window.
While your programme is still in Debug mode (the yellow line will still be there, if it is), click Debug > Windows > Locals from the menu bar. You should see the following in the bottom left of your screen:
The locals window
Locals means "Local variables". That is, variables declared in this section of the code. The variables iletter and LetterCount are showing in the window. The value of these variables is also displayed: 0Nothing and 0. Press F10 and these values will change. This is the Locals window after one go round the loop:
Press the F10 key to advance the programme
The variable i is now 2; letter is "D", and LetterCount, is still 0. Keep pressing F10 and go round the loop a few times. What do you notice?
You should notice that the value in letter never moves on. It is "D" all the time. And that's why LetterCount never gets beyond 0. 

Exercise J

Why does LetterCount never gets beyond 0? Correct the code so that your textbox displays the correct answer of 3 when the programme is run.

And that's it for Error checking and debugging. It can often be an art form in itself. But one well worth persevering with: it could save you a lot of headaches!


Comments