1.1 version 3: Restore exception
Next, change:
__except (Except_Filter (3, Exception_Continue_Search))
for:
__except (Except_Filter (3, Exception_Continue_execution)
Rebate and run. You can see this output:
0: Before first try
1: TRY
2: TRY
3: TRY
4: TRY
4: Raising Exception
3: filter => eXception_continue_execution
4: After EXCEPTION
4: Handling Normal Termination
3: Continuation
2: Continuation
2: Handling Normal Termination
1: Continuation
0: Continuation
Because the abnormal filter of the third layer has captured an abnormality, the filter of the first layer will not be evaluated. The capture of the abnormality evaluation is exception_continue_execution, so it is recovered. The abnormality handler will not be entered, and will be executed normally from the abnormality.
1.2 version 4: abnormal termination
Such a structure:
__TRY
{
/ * ... * /
Return;
}
or:
__TRY
{
/ * ... * /
Goto label;
}
__finally
{
/ * ... * /
}
/ * ... * /
Label:
It is considered that the TRY block is extremely terminated. If you call an abnormalterMination () function later, you will return a non-0 value, just like an exception still exists.
To see its effect, change these two lines:
Trace (4, "Raising Exception");
RaiseException (Exception_code, 0, 0, 0);
for:
Trace (4, "EXITING TRY Block");
Goto end_4;
The TRY block of the 4th floor is not ended by an exception, and is now the end of the goto statement. operation result:
0: Before first try
1: TRY
2: TRY
3: TRY
4: TRY
4: EXITING TRY BLOCK
4: Handling Abnormal Termination
3: Continuation
2: Continuation
2: Handling Normal Termination
1: Continuation
0: Continuation
The termination processing function of the 4th floor considers that it is dealing with an abnormality, although there is no exception. (If there is an abnormality, we can at least see from an output information of an exception filter.)
Conclusion: You can't just rely on the abnormalterMination () function to determine if an exception still exists.
1.3 version 5: Normal termination
If you want to terminate a TRY block normally, you want the AbnormalterMination () function to return false, you should use the Microsoft's unique keyword __leave. If you want to verify, change:
Goto end_4;
for:
__leave;
Re-build and run, the result is:
0: Before first try
1: TRY
2: TRY
3: TRY
4: TRY
4: EXITING TRY BLOCK
4: Handling Normal Termination
3: Continuation
2: Continuation
2: Handling Normal Termination
1: Continuation
0: Continuation
The output of version 4 is very close, except: The termination processing function of the 4th floor is now considered to end the normal end.
1.4 version 6: implicit exception
The previous program version processed is an exception generated by the user. SEH can also handle the exception thrown by Windows.
Change this line:
Trace (4, "EXITING TRY Block");
__leave;
for:
Trace (4, "iMPlicitly Raising Exception);
* ((char *) 0) = 'x';
This causes the Windows memory operation anomaly (reference null pointer). Then change:
__except (Except_Filter (3, Exception_Continue_execution)
for:
__except (ExcePt_Filter (3, Exception_execute_Handler)
To capture the program and process an exception.
The execution result is:
0: Before first try
1: TRY
2: TRY
3: TRY
4: TRY
4: Implicitly Raising Exception
3: filter => eXception_execute_handler
4: Handling Abnormal Termination
3: Handling Exception
2: Continuation
2: Handling Normal Termination
1: Continuation
0: Continuation
As we expect, Windows triggered an exception in nested level 4 and captured by the exception handler of the hierarchy 3.
If you want to know the captured precise exception code, you can let the exception to the outside of Main, doing it in version 2. To this end, change:
__except (ExcePt_Filter (3, Exception_execute_Handler)
for:
__except (Except_Filter (3, Exception_Continue_Search))
Results Dialog After pressing "Details", the information displayed is very similar to the user's exception.
Figure 3 Memory Exception Dialog
And version 2 dialog box is different, the last showed special exception code, this time, "Invalid Page Fault" - more user friendly.
1.5 C consideration
In all C-compatible exception handling systems, SEH is undoubtedly the most complete and flexible (at least in a Windows environment). Ironically, it is also the least flexible in the environment other than the Windows system, which is tied together with a special running platform and Visaul C source code compatible complaints together.
If you only use the C language, it is not considered to port it to the Windows platform, SEH is very good. However, if C is used and considering portability, I strongly recommend that you use standard C abnormal processing without SEH. You can use SEH and standard C exceptions in the same program, only one limit: if an object is defined in the function with the SEH TRY block, and this object does not have a Non-Trivial destructor The compiler will report an error. In the same function, use such objects and SEH __TRY, you must ban standard C exception handling. (Visual C defaults to standard C exception handling. You can open it with the command line parameter / gx or Visual Studio's Project Settings dialog.)
In future articles, I will review the SEH when discussing standard C abnormalities. I want to integrate SEH into the mainstream of C , and mapping the structured exception and Windows runtime support to C exceptions and standard C runtime support.
1.6 MFC abnormal treatment
Note: This section I need to pre-reference a little bit of standard C exception handling, but will immediately introduce them next time. This quote is inevitable, but it is not surprised because Microsoft has built their MFC abnormal syntax and semantics on the standard C abnormal syntax and semantic basis.
I have been valid for C and C so far. In addition, Microsoft has a solution to the C program: MFC exception handling class and macro. Microsoft now believes that the MFC exception handling system is outdated and encourages you to use standard C abnormal processing as much as possible. However, Visual C still supports MFC anomaly and macros, so I will give it a brief introduction.
Microsoft implements MFC3.0 and later in standard C anomaly. So you must activate the standard C exception to use the MFC, even if you don't intend to explicitly use these anomalies. As mentioned earlier, you have to ban the standard C anomalies to use SEH, which means you can't use the MFC macro and SEH at the same time. Microsoft plain text stipulates that the two exception systems are mutually exclusive and cannot be mixed in the same procedure.
SEH is extended to the compiler key set, and the MFC defines a set of macros:
l try
l catch, and_catch, and end_catch
l throw and throw_last
These macros are very elephant in C Try, Catch, and Throw.
In addition, the MFC provides an abnormal class system. All the names of all the forms of cxxxexception are derived from abstract class CEXCEPTION. This is similar to the derived system starting from Std :: Exception in
For each MFC exception class CxxxException, there is a global auxiliary function AFXTHROWXXXEXCEPTION (), it constructs, initializes, and throws this class object. You can use these auxiliary functions to handle predefined exception types, with THROW to process custom objects (of course, they must be derived from CEXCEPTION).
Basic design principles are:
l The use of the TRY block contains code that may produce an exception.
l Detect and handle exceptions with CATCH. The exception handler is not really captured, which actually captures pointers pointing to an exception. The MFC relies on dynamic types to distinguish an abnormal object. To compare, SEH queries the abnormality code at runtime to distinguish an exception.
l Tread multiple exception handles on a TRY block, each capturing a different type of C static type. The first processing function uses the macro Catch, and later uses and_catch, end the processing function queue with the END_CATCH.
l MFC you might trigger an exception, you can also explicitly trigger an exception (via the Throw or MFC auxiliary function). Inside the exception handler, you can throw the most recent capture again with throw_last.
l Exceptions are triggered, and the exception handler will be searched out from the outside, as SEH. Search is stopped in finding an exception handler for a type matching. All exceptions are terminated. Unlike SEH, the MFC does not terminate the process, you must rely on the destructor of the local object.
A small MFC example, including most of the topics:
#include
#include "afxwin.h"
Void f ()
{
Try
{
Printf ("Raising Memory Exception / N);
AfXTHROWMEMORYEXCEPTION ();
Printf ("This Line Should Never APPEAR / N");
}
Catch (CEXCEPTION, E)
{
Printf ("Caught Generic Exception; Rethrowing / N");
Throw_last ();
Printf ("This Line Should Never APPEAR / N");
}
END_CATCH
Printf ("This Line Should Never APPEAR / N");
}
int main ()
{
Try
{
f ();
Printf ("This Line Should Never APPEAR / N");
}
Catch (cfileException, e)
{
Printf ("CAUGHT FILE EXCEPTION / N");
}
And_catch (cmemoryexception, e)
{
Printf ("Caught Memory Exception / N);
}
/ * ... Handlers for other CEXCEPTION-DERIVED TYPES ... * /
And_catch (CEXCEPTION, E)
{
Printf ("Caught Generic Exception / N);
}
END_CATCH
Return 0;
}
/ *
When Run Yields
Raising Memory Exception
Caught Generic Exception; Rethrowing
Caught Memory Exception
* /
Remember, the exception handler captures the pointer to the object, not the actual object. So, handle functions:
Catch (CEXCEPTION, E)
{
// ...
}
Define a partial pointer CEXCEPTION * E points to the throwing exception object. Based on C polymorphism, this pointer can reference any object derived from CEXCeption.
If the same TRY block has multiple processing functions, they match the search from top to bottom. So, you should put the process of handling the object of the most rated object in front, otherwise, the process of dealing with the process will not receive any abnormalities (rejoiced again). Because you typically want to capture CEXCEPTION, MFC defines several CEXCEPTION unique macro:
l Catch_all (e) and and_catch_all (e), equivalent to catch (CEXCEPTION, E), and AND_CATCH (CEXCEPTION, E).
l End_catch_all, end catch_all ... and_catch_all queue.
l End_TRY is equivalent to catch_all (e); end_catch_all. This makes the trory ... End_TRY do not process functions or to receive all thrown exceptions.
This referred to the abnormal object is implicitly destructed and returned by the MFC. This is different from the standard C exception handler, and the MFC exception handle does not allow anyone to acquire ownership of the captured pointer. Therefore, you cannot use the MFC and the standard C system to simultaneously handle the same exception object; otherwise, the memory leak will result in memory leaks: Take the object that has been destructed, and repeat the destructor and return the same object.
1.7 small knot
There are also several other articles that explore structured abnormalities and MFC abnormal macros in MSDN.
Next time I will introduce standard C abnormalities, outline their characteristics and basic principles. I will also compare them with the methods that have already been seen.