Document directory
- How to use them together?
- Continue to go deep into the example just now
- Can the C ++ Exception Handling Model capture seh exceptions?
- Seh and C ++ exception models in the "Restricted Area" when used together"
- Summary
Reproduced from-http://blog.programfan.com/article.asp? Id = 9865
In the previous article, we saw that the try-try t and try-finally mechanisms of seh can be well used in the C ++ Program (although this is not recommended in msdn ), in this article, we will continue to discuss how to use the try-catch exception mechanism (seh) and try-catch exception mechanism (C ++ exception model) in the C ++ program).
Are you ready? This is a bit complicated!
How to use them together?
Let's look at the example first. It is still modified based on the Code of the original routine. The modified code is as follows:
// Note that this is the c ++ program, file name: SEH-test.cpp
# Include "stdio. H"
Class
{
Public:
Void F1 (){}
// Throw a C ++ exception
Void F2 () {Throw 888 ;}
};
// This function uses try-catch to handle exceptions, that is, C ++ exception handling.
Void test1 ()
{
A A1;
A A2, A3;
Try
{
A2.f1 ();
A3.f2 ();
}
Catch (INT errorcode)
{
Printf ("catch exception, error code: % d/N", errorcode );
}
}
// This function has not changed, and still uses the try-try t exception mechanism, that is, the seh mechanism.
Void test ()
{
Int * p = 0x00000000; // pointer to null
_ Try
{
// Call the test1 function here
Test1 ();
Puts ("in try ");
_ Try
{
Puts ("in try ");
// Causes an access violation exception;
// Cause a storage exception
* P = 13;
Puts ("won't be executed here ");
}
_ Finally
{
Puts ("in finally ");
}
Puts ("This will not be executed here ");
}
_ Partition T (puts ("in filter 1"), 0)
{
Puts ("in bytes T 1 ");
}
}
Void main ()
{
Puts ("hello ");
_ Try
{
Test ();
}
_ Partition T (puts ("in filter 2"), 1)
{
Puts ("in bytes T 2 ");
}
Puts ("world ");
}
The above program can be compiled and run correctly (same as expected, it also complies with the rules of the C ++ Exception Handling Model and the rules of the seh exception model ). The result is as follows:
Hello
Catch exception, error code: 888
In try
In try
In filter 1
In filter 2
In finally
In bytes T 2
World
Press any key to continue
Continue to go deep into the example just now
In the above routine, although there is both a try-catch mechanism and a try-catch t mechanism in the same program, of course, this is completely equivalent to the hybrid use of seh and C ++ exception models. However, please note that these two mechanisms are actually completely split, and they are completely split into the interior of the two functions. That is to say, these two mechanisms do not fully interact with each other. In other words, they are not actually a mix of the two exception handling mechanisms. Here we will continue to provide a more absolute example. Let's take a look at the code, as shown below:
// Note that this is the c ++ program, file name: SEH-test.cpp
# Include "stdio. H"
Class myexception
{
Public:
Myexception () {printf ("construct a myexception object/N ");}
Myexception (const myexception & E) {printf ("copy a myexception object/N ");}
Operator = (const myexception & E) {printf ("copy a myexception object/N ");}
~ Myexception () {printf ("destructor A myexception object/N ");}
};
Class
{
Public:
A () {printf ("constructing a A Object/N ");}
~ A () {printf ("destructor A Object/N ");}
Void F1 (){}
// Note that an exception object of the myexception type is thrown.
Void F2 () {myexception E; throw E ;}
};
// This function uses try-catch to handle exceptions, that is, C ++ exception handling.
Void test1 ()
{
A A1;
A A2, A3;
Try
{
A2.f1 ();
A3.f2 ();
}
// Although there is a catch block, it cannot catch the C ++ exception object thrown above
Catch (INT errorcode)
{
Printf ("catch exception, error code: % d/N", errorcode );
}
}
// This function has not changed, and still uses the try-try t exception mechanism, that is, the seh mechanism.
Void test ()
{
Int * p = 0x00000000; // pointer to null
_ Try
{
// Call the test1 function here
// Note: The test1 function throws a C ++ exception object.
Test1 ();
Puts ("in try ");
_ Try
{
Puts ("in try ");
* P = 13;
Puts ("won't be executed here ");
}
_ Finally
{
Puts ("in finally ");
}
Puts ("This will not be executed here ");
}
_ Partition T (puts ("in filter 1"), 0)
{
Puts ("in bytes T 1 ");
}
}
Void main ()
{
Puts ("hello ");
_ Try
{
Test ();
}
// Can the C ++ exception object be captured here? Wait and see!
_ Partition T (puts ("in filter 2"), 1)
{
Puts ("in bytes T 2 ");
}
Puts ("world ");
}
After carefully reading the above program, it is not difficult to see that the seh and C ++ exception models have actually interacted with each other. The upper main () function and test () function () the function uses the try-catch t statement to handle exceptions, while the lower-level test1 () function uses the standard try-catch statement to handle exceptions, and the lower-level test1 () will the C ++ exception thrown by the function be caught by the try-try t in the upper layer? Check the running result! As follows:
Hello
ConstructObject
ConstructObject
ConstructObject
Construct a myexceptionObject
Copy A myexceptionObject
In filter 1
In filter 2
Parses a myexceptionObject
DescribeObject
DescribeObject
DescribeObject
In bytes T 2
World
Press any key to continue
Are the results consistent with expectations of friends? It is indeed a try-nothing t block in the upper layer. It can capture the C ++ exception thrown by the test1 () function in the lower layer, and the process is correct, that is, it complies with the rules of the seh exception model and the C ++ exception model. At the same time, the most valuable thing is that the three local variables in the test1 () function are correctly parsed (this is amazing! The specific mechanism is not discussed in detail here. I will discuss it later in the article "Implementation of the exception mechanism ).
Careful programmers may find some "problems" from the running results of the above program. What? That is,"MyexceptionObjectIt is constructed twice, but only once. Haha! This may be one of the reasons why the two exception handling mechanisms are not recommended in msdn! Although this problem does not have a major destructive impact on the entire program, the hero, a Yu, insists that if we misuse try-catch and try-catch in programming, this not only affects the overall structure and semantics of our program, but also causes memory resource leakage and other unstable factors.
In short, using the try-upon t mechanism in a C ++ program is necessary only in the function scope at the top level (for example, in the system Runtime library or in the hooks of plugin. For example, in a program written by VC, whenever a crash event occurs during program running, the system will always pop up an "application error" box, as shown below:
How is the NT operating system implemented? It is very simple. It adopts the try-retry t mechanism in the top-level function of the VC Runtime Library. Do not believe it. Let's look at the following code!
Can the C ++ Exception Handling Model capture seh exceptions?
Haha! Ah Yu smiled. Do you still need to ask? Of course, the powerful feature of the C ++ Exception Handling model provided by VC is that it can not only capture C ++ exceptions, but also capture system-level seh exceptions. It uses catch (...) The catch (…) syntax (...) We also focus on this point in terms of syntax. However, here is a practical example. The Code is as follows:
Class myexception
{
Public:
Myexception () {printf ("construct a myexception object/N ");}
Myexception (const myexception & E) {printf ("copy a myexception object/N ");}
Operator = (const myexception & E) {printf ("copy a myexception object/N ");}
~ Myexception () {printf ("destructor A myexception object/N ");}
};
Class
{
Public:
A () {printf ("constructing a A Object/N ");}
~ A () {printf ("destructor A Object/N ");}
Void F1 (){}
// Throw a C ++ exception
Void F2 () {myexception E; throw E ;}
};
Void test ()
{
Int * p = 0x00000000; // pointer to null
_ Try
{
Puts ("in try ");
_ Try
{
Puts ("in try ");
// Causes an access violation exception;
// Cause a storage exception
* P = 13;
// Haha, pay attention to this statement
Puts ("won't be executed here ");
}
_ Finally
{
Puts ("in finally ");
}
// Haha, pay attention to this statement
Puts ("This will not be executed here ");
}
_ Partition T (puts ("in filter 1"), 0)
{
Puts ("in bytes T 1 ");
}
}
Void test1 ()
{
A A1;
A A2, A3;
Try
{
// Here a seh type system exception is generated
Test ();
A2.f1 ();
A3.f2 ();
}
// Can this problem be captured?
Catch (...)
{
Printf ("catch unknown exception/N ");
}
}
Void main ()
{
Puts ("hello ");
_ Try
{
Test1 ();
}
_ Partition T (puts ("in filter 2"), 0)
{
Puts ("in bytes T 2 ");
}
Puts ("world ");
}
The above program is very simple and does not need further discussion. Of course, we can go further, because the C ++ Exception Handling model not only can normally capture Seh-type system exceptions, it can also convert a system exception of the seh type to a C ++ type exception. I think this should be elaborated in a separate article. In fact, this is also discussed in detail in many books on window system programming.
Seh and C ++ exception models in the "Restricted Area" when used together"
Just now we can see that it is a small problem to use try-catch t to capture C ++ exceptions, but this is not a restricted area after all. So what is the "Restricted Area" for seh and C ++ exception models in hybrid use? Let's take a look at the example. The Code is as follows:
// Note that this is the c ++ program, file name: SEH-test.cpp
# Include "stdio. H"
Void main ()
{
Int * p = 0x00000000; // pointer to null
// Here is the exception handling Syntax of Seh.
_ Try
{
Puts ("in try ");
// Here is the exception handling Syntax of C ++.
Try
{
Puts ("in try ");
// Causes an access violation exception;
// Cause a storage exception
* P = 13;
// Haha, pay attention to this statement
Puts ("won't be executed here ");
}
Catch (...)
{
Puts ("catch anything ");
}
// Haha, pay attention to this statement
Puts ("This will not be executed here ");
}
_ Partition T (puts ("in filter 1"), 1)
{
Puts ("in bytes T 1 ");
}
}
Friends! Don't rush to compile and test the above small program. First, let's guess what the result will be? Did you think of it? Try it out! Are you surprised by the actual results? By the way, true, VC reports a compilation error ("error c2713: only one form of exception handling permitted per function "). So why? Here, the hero, a Yu, must be "ignorant and speechless", because the Exception Handling Mechanism Implemented by VC, whether it is a try-catch model or a try-catch model, they all use functions as a basic "Analysis and Control" goal, that is, if an exception handling mechanism is used in a function, when the VC compiler compiles the function, it inserts some "code and information" into this function (the Code refers to the callback function when an exception occurs in this function, information mainly refers to some necessary linked lists related to exceptions. Therefore, each function can have only one such list ("code and information "), therefore, a function can only use one form of exception handling rules. Friends! I suddenly realized it! In fact, this is not the most incredible. In another special case, let's look at the following example. The Code is as follows:
Class
{
Public:
A () {printf ("constructing a A Object/N ");}
~ A () {printf ("destructor A Object/N ");}
Void F1 (){}
Void F2 (){}
};
Void main ()
{
_ Try
{
A A1, A2;
Puts ("in try ");
}
_ Partition T (puts ("in filter 1"), 1)
{
Puts ("in bytes T 1 ");
}
}
In fact, the above program seems to have nothing special on the surface? Friends! Take a closer look. Is there anything special? Compile the program. It's strange! Yes, it also reports an error during compilation. This is the information generated during compilation on my machine, as shown below:
-------------------- Configuration: exception-Win32 debug --------------------
Compiling...
Seh-test.cpp
F:/exception/seh-test.cpp (214): Warning c4509: Nonstandard extension used: 'main' uses seh and 'a2 'has destructor
F:/exception/seh-test.cpp (211): See Declaration of 'a2'
F:/exception/seh-test.cpp (214): Warning c4509: Nonstandard extension used: 'main' uses seh and 'a1' has destructor
F:/exception/seh-test.cpp (211): See Declaration of 'a1'
F:/exception/seh-test.cpp (219): Error c2712: cannot use _ Try in functions that require object Unwinding
Error executing cl.exe.
Creating browse info file...
Exception.exe-1 error (s), 2 warning (s)
So what does the above error message mean? I wonder if many of my friends have encountered this inexplicable compilation problem. In fact, this is really confusing. Is the program very simple? In addition, only the try-try t Syntax of seh exception model is used in the program, and even the combination of seh and C ++ exception model does not exist. So what are the causes of compilation errors? Tell you the truth! In fact, the hero, a Yu, had a hard time thinking about this issue. After some in-depth and meticulous research, he realized the real cause.
The reason is that the compilation error is also caused by the failure of an exception handling mechanism in two forms in a function. Ah! This is not even more confusing. Otherwise, my friends will understand that this is because in the C ++ Exception Handling model, ensure that the relevant local variables are correctly released (that is, the Destructor is called). It must track the creation process of each "object, this kind of object analysis process caused by exceptions is called "unwind" (remember the term mentioned in the previous content many times). Therefore, if a function contains a local object, then it will certainly have a C ++ Exception Handling Mechanism (that is, it will insert some code and information for the function to handle C ++ exceptions, if the try-again t mechanism is used in this function, isn't it a conflict? So the compiler reports an error because it cannot be processed! Haha! Dear friends, have you made the problem clear?
Summary
• Seh and C ++ exception models can be used together. But it is best to follow the msdn advice: Use try-catch and try-finally in the C program, while the C ++ program should use try-catch.
• In hybrid use, the C ++ exception model can capture seh exceptions, while the seh exception model can also capture C ++ exceptions. The latter usually has a small problem. It is generally used to improve and ensure the reliability of the product (that is, the try-retry t statement is used in top-level functions to catch any exceptions)
• In the Exception Handling Mechanism Implemented by VC, whether it is a try-catch model or a try-catch model, they all use functions as a basic "Analysis and Control" goal, that is, only one exception handling rule can be used in a function. Otherwise, compilation will be "shelled ".
In the next article, the hero, a Yu, intends to discuss in detail some advanced usage skills on the C ++ Exception Handling Model, that is, "how to convert a seh system exception to a C ++ type exception? ", Programmers, continue!