The Call Stack

The Call Stack

When you add structured error handling to your code, it's important to understand how it works with respect to calling other procedures from within a protected Try block. If you call a procedure within a protected Try block, code execution transfers to that procedure. If an error occurs in that procedure, it will be handled locally by any defined Try…Catch blocks. If, however, no structured handling code is available in the procedure, the code transfers back to the caller. If no error handling is defined in the calling procedure, the code transfers execution up the calling stack until it finds an appropriate handler. If no handler is found, the error is handled (in a rather unfriendly way) by the common language runtime.

Let's say we call procedure1, which has a Try…Catch block. Then procedure1 calls procedure2, which subsequently calls procedure3. Now procedure3 attempts to divide by zero, which throws an exception.

When the code enters the protected Try block in procedure1, that error handler becomes active. As the execution transfers to the other procedures and an error is encountered in procedure3, the runtime checks whether an active error handler is defined locally. If the runtime doesn't find one, control continues up the call stack until an active handler is found. Consider the following example:

Call procedure1()

In procedure1 we have a protected Try...Catch block. We will catch any CLR generated exception in that section. When the code completes, the Finally block is entered. As soon as code enters the Try block in procedure1, and until each line within the Try block is executing, that handler remains active.

Private Sub procedure1()     Try         sErrorMessage.Append("In procedure1, calling procedure2" _             & CtrlChr.CrLf)         procedure2()     Catch e As Exception         sErrorMessage.Append("Catch block in procedure1: " & _             e.ToString & CtrlChr.CrLf)     Finally         sErrorMessage.Append("Finally in procedure1" & _             CtrlChr.CrLf)         MessageBox.Show(sErrorMessage.ToString, _             "Error Stack Example", MessageBoxButtons.OK, _             MessageBoxIcon.Information)     End Try End Sub Private Sub procedure2()     sErrorMessage.Append("In procedure2, calling procedure3" & _         CtrlChr.CrLf)     procedure3()     sErrorMessage.Append("In procedure2, returned from " & _         "procedure3 - never gets here" & CtrlChr.CrLf) End Sub Private Sub procedure3()     Dim iNumerator As Integer = 32     Dim iDenominator As Integer = 0     Dim iResult As Integer = 0     sErrorMessage.Append("In procedure3, generating error" & _         CtrlChr.CrLf)     iResult = iNumerator / iDenominator     sErrorMessage.Append("In procedure3, after error – " & _         "never gets here" & CtrlChr.CrLf) End Sub

You can see that we go from procedure1 to procedure2 to procedure3 and then generate an error. When the exception is thrown in procedure3, there is no active handler, so the code is transferred to procedure2 and finally to procedure1, which does indeed have an active handler. Be sure you understand how the calling stack unwinds until a handler is found. Of course, the Finally block will always execute, as shown in Figure 7-18.

Figure 7-18

The call stack unwinds until a handler is found.

The call stack unwinding feature is great; we get the call stack automatically, which can be quite useful when diagnosing the source of an error. Notice that the source of the error, procedure3, is at the top of the stack. The error winds down to procedure1, where it is actually caught and handled.



Coding Techniques for Microsoft Visual Basic. NET
Coding Techniques for Microsoft Visual Basic .NET
ISBN: 0735612544
EAN: 2147483647
Year: 2002
Pages: 123
Authors: John Connell

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net