Question:
int* p = 0x00000000; // pointer to NULL
puts( "hello ");
__try{
puts( "in try ");
__try{
puts( "in try ");
*p = 13; // causes an access violation exception;
}__finally{
puts( "in finally ");
}
}__except(puts( "in filter "), 1){
puts( "in except ");
}
puts( "world ");
/*
hello
in try
in try
in filter
in finally
in except
world
*/
I listed the answers to the questions above.
I have never seen the _ Try statements in the form of C ++. Next I will try and catch; _ Try ,__ finally; _ try, _ handle t: The three tags used for exception handling are described one by one.
- C ++ Exception Handling: Try, catch
try
{
// possible errors
// If there is something wrong, just--
throw ... // Initialize an exception object
}
catch (type name [formal parameter name]) / * exception specifier * /
{
}
catch (type name [formal parameter name])
{
}
The exception handling in C ++ is very simple, that is, the above three keywords. Note that throw in C ++ does not have finally in Java or other languages after catch.
Q: Why does C ++ not provide a "finally" structure?
A: Because c ++ provides another mechanism that can completely replace finally, and this mechanism almost always works better than finally: "allocating resources is initialization ". (See section 14.4 of the C ++ programming language) The basic idea is to use a local object to encapsulate a resource, in this way, the destructor of a local object can automatically release resources. In this way, programmers will not "forget to release resources. [Note: The "lifecycle" mechanism of the C ++ object is remembered for him: O)] The following is an example:
class File_handle {
FILE* p;
public:
File_handle(const char* n, const char* a)
{ p = fopen(n,a); if (p==0) throw Open_error(errno); }
File_handle(FILE* pp)
{ p = pp; if (p==0) throw Open_error(errno); }
~File_handle() { fclose(p); }
operator FILE*() { return p; }
// ...
};
void f(const char* fn)
{
File_handle f(fn,"rw"); // open fn for reading and writing
// use file through f
}
In a system, each resource requires a "Resource Bureau handle" object, but we do not have to write a "finally" statement for each resource. In an actual system, resources are acquired and released much more frequently than the types of resources. Therefore, the "resource allocation is initialization" mechanism produces less code than the "finally" mechanism.
Now, let's look at the other two sets of exception model mechanisms. They are the seh model provided on Windows operating systems, that is, when calling in C ++, it is actually calling Windows APIs.
Seh, also known as structured exception handling, is a way to handle exceptions when designing a Windows operating system.
This set of exception handling mechanisms is very similar to C ++, except that the keyword is catch rather than catch.
Catch and catch t are different:The catch keyword is often followed by a function parameter. It can be an exception data object of various types, but the _ struct t keyword is different, it is followed by an expression (it can be an expression of various types)
The following is an example:
void main ()
{
puts ("hello");
// define monitored code modules
__try
{
puts ("in try");
}
// define exception handling module
__except (1)
{
puts ("in except");
}
puts ("world");
}
1. The monitored code module is executed (that is, the Code defined by _ Try );
2. If no exception occurs during the above code execution, the control flow will be transferred to the Code module after the _ limit t clause;
3. Otherwise, if an exception occurs, the control flow enters the expression after _ expect T.Calculate the value of this expression.Then, the corresponding processing is determined based on this value.
Exception_continue_execution (-1) The exception is ignored. The control flow continues to run after the exception occurs.
Prediction_continue_search (0) exceptions are not identified, that is, the current _ partition t module is not the correct Exception Handling Module corresponding to this exception error. The system continues to search for an appropriate _ partition t module in the try-release T domain on the previous layer.
Prediction_execute_handler (1) the exception has been identified, that is, the current Exception error. The system has found and confirmed that the _ HANDLE t module is the correct Exception Handling Module. The control flow enters the _ blocks t module.
Summary:
(1) The C ++ exception model is defined by the try-catch syntax, while the seh exception model is defined by the try-catch syntax;
(2) similar to the C ++ exception model, the try-example t also supports multi-layer try-example t nesting.
(3) Unlike the C ++ exception model, in the try-try t model, a try block can only have one limit t block. In the C ++ exception model, A try block can have multiple catch blocks.
(4) similar to the C ++ exception model, in the try-try t model, the rules for searching the exception module are also carried out step by step. However, the difference is that the C ++ exception model performs a matching search based on the exception object type, while the try-try t model is different, it is determined by the value of an expression. If the expression value is 1 (prediction_execute_handler), the exception handling module is found. If the value is 0 (prediction_continue_search ), it indicates to continue searching for other exception handling modules that may match in the try-again t domain of the previous layer. If the value is-1 (prediction_continue_execution), this exception is ignored. Note that this value is rarely used, it can easily lead to unpredictable results, such as endless loops and even program crashes.
(5) The expression following the _ comment t keyword. It can be a variety of expressions. For example, it can be a function call, a conditional expression, or a comma expression, or an integer constant. The most commonly used function expression is a function expression that uses the getexceptioncode () or getexceptioninformation () function to obtain the current Exception error information, so that programmers can effectively control the classification of exception errors.
(6) In the seh Exception Handling Model, exceptions are classified into two categories: system exceptions and software exceptions. The software exception is thrown through the raiseexception () function. The role of the raiseexception () function is similar to the throw statement in the C ++ exception model.
The syntax of a try-finally statement is similar to that of a try-finally statement. The difference is that __finally does not have an expression after it, because the try-finally statement is not used for exception processing, therefore, it does not need an expression to determine the type of the current Exception error. In addition, like the try-Finally t statement, try-finally can also be nested in multiple layers, and a function can have multiple try-finally statements, whether nested, or parallel. Of course, try-finally multi-layer nesting can also be cross-function.
Key points:"No matter under what circumstances, code in the Finally block area will be executed when it leaves the current scope"
void tmain ()
{
puts ("hello");
__try
{
puts ("__ try block");
// Note that the following return statement directly returns the function
return;
}
__finally
{
puts ("__ finally block");
}
puts ("world");
}
The program running result is as follows:
Hello
_ Try Block
_ Finally block
Press any key to continue
Summary:
_ When a Finally block is executed, there are three situations.
FirstIt is the code executed in the _ Finally block area in sequence. This situation is simple and easy to understand;
SecondWhen the program control flow caused by a goto or return statement leaves the current _ Try block scope, the system automatically calls the _ Finally block code;
ThirdWhen an exception occurs in the _ Try block, the control flow of the program leaves the current _ Try block scope. In this case, the system automatically calls the _ Finally block.
Whether it is 2nd or 3rd cases, there is no doubt that they will cause a lot of system overhead. When the compiler compiles such program code, it will prepare a lot of additional code for both cases.
Generally, it is referred to as "localunwinding" and "globalunwinding" in 2nd cases )". This will be analyzed in detail when we discuss seh implementation later.
In 3rd cases, that is, global expansion caused by exceptions, this may be unavoidable for programmers, this is because when you use the exception handling mechanism to improve program reliability and robustness, it will inevitably lead to other performance overhead. Haha! In fact, the world is fair, and there are gains and losses.