) Structured exception handling in Windows program design

Source: Internet
Author: User
Tags finally block
Question: [original] structured exception handling in Windows program design
Author: Arctic star 2003
Time: 2006-09-20, 20: 21
Chain: http://bbs.pediy.com/showthread.php? T = 32222

Directory:
I. concepts and features of seh
Ii. Basic seh usage
1. End the Abnormal Program
(1) natural and non-natural exits of try Blocks
(2) Cleaning function of finally blocks and impact on program structure
(3) keyword _ leave
2. Exception Handling Program
(1) Basic Process of Exception Handling
(2) exception filter
(3) Global Expansion
(4) pause Global Expansion
3. unhandled exceptions (top-level Exception Handling)
Iii. Introduction to Seh-related data structures
1. prediction_pointer Structure
2. prediction_record Structure
3. exceptoin_registration Structure
4. Exception Handling Link Structure
IV. Implementation of VC ++ compiler-level seh
1. Abnormal frame of VC Extension
2. Abnormal frame STACK layout of VC
3. Two instance programs: displaying abnormal frame information
4. instance analysis and features
5. Fixed layer Exception Handling in VC
6. VC search exception handling process

V. References

--------------------------------------------------------------------------

Preface:
This article should be the most serious one I have written. I wrote it intermittently for nearly a month. From the initial review, I collected more information, repeat the ideas, read the relevant source code in the Windows source code, design the overall framework of the article, and go to the detailed design of each part, including the flowchart design. Every process is not smooth. Due to the time, there can only be 2 ~ Three times in front of the computer for a long time, so the idea has been interrupted, and the preparation of articles is not smooth. Some ideas may have no idea where to forget them, but I also try to share all relevant knowledge points. This article focuses on the introduction of seh principles. From a simple perspective, it is relatively simple, but if you use the seh mechanism properly, this is largely related to the user's understanding of Seh. For specific implementation, this article only introduces the key points and points to attention, for more information, see [1].

I. concepts and features of seh

Seh, structured exception handling, is introduced into the operating system as a system mechanism and is independent of the language. Using seh in our own programs allows us to focus on developing key functions, while uniformly handling possible exceptions in the program, making the program more concise and readable.

When seh is used in a program, it becomes compiler-related. The burden caused by this is mainly borne by the Compilation Program. For example, the Compilation Program will generate some tables to support the seh data structure and provide callback functions.

Ii. Basic seh usage

1. End the Abnormal Program
An end exception program ensures that a code block is called and executed. The structure of the end exception program is as follows:
_ Try {
// Protected code
}
_ Finally {
// End the processing program
}
(1) natural and non-natural exits of try Blocks
The try block may exit because of a return, Goto, exception, or other non-natural reasons. It may also exit because of successful execution. However, no matter how the try block exits, the Finally block content will be executed. See the following two programs:

By using the end handler, you can avoid premature execution of the Return Statement. When retrun tries to exit the try block, compile the program to ensure that the code in the Finally block is first executed. This is actually a local expansion process. When the force control is transferred from the early exit of the try block to the Finally block, it will cause local expansion.

(2) Cleaning function of finally blocks and impact on program structure
A friend who has written software generally has the following impact: in the coding process, you need to add a check to check whether the function is successfully executed. If the code is successful, execute this check, otherwise, you need to perform some extra cleanup operations, such as releasing the memory and disabling the handle. If there are not many tests, there will be no impact. However, if there are a lot of tests and the logical relationships in the software are complicated, it is often necessary to make a lot of effort to achieve a complicated detection and judgment. The results will make the program look complex, greatly reducing the readability of the program, and the program size is also increasing.

As a matter of fact, we can use seh to solve this problem. We need to add some proper judgment to the cleanup code of some related functions in the Finally block, you do not need to go back to every possible failure to add cleanup code. The following funsamplea function is a common function. funsampleb introduces the seh end handler mechanism:

The functions of these two functions are the same. We can see that the cleanup function (closehandle) in funsamplea is everywhere, while the cleanup function in funsampleb is all concentrated in finally blocks, if you only need to read the content of the try block when reading the code, you can understand the program process. These two functions are very small, so you can understand the differences between the two functions.

(3) keyword _ leave

Using the _ leave keyword in the try block will jump the program to the end of the try block and naturally enter the Finally block.

For funsampleb in the above example, the three return values in the try block can be replaced by _ leave. The difference between the two is that using return will cause the try to exit the system prematurely and expand the system to increase the system overhead. If _ leave is used, the try block will naturally exit, with much less overhead.

However, in one case, _ leave must be used instead of return, that is, some functions must be executed after the Finally block, as shown below:


2. Exception Handling Program
The exception handling program can handle exceptions in the program. The structure of the exception handling program is as follows:
_ Try {
// Protected code
}
_ Effect (/* exception filter */){
// Exception handler
}

(1) Basic Process of exception handling (Note: This flowchart comes from references [1])

(2) exception filter

The exception filter has only three possible values (defined in excpt. h of Windows ):
Prediction_execute_handler
Prediction_continue_serch
Prediction_continue_execution

The following are two basic usage methods:
Method 1: directly use one of the three return values of the filter
_ Try {
......
}
_ Handler T (exception_execute_handler ){
......
}

Method 2: custom filter
_ Try {
......
}
_ Counter T (myfilter (getexceptioncode ()))
{
......
}

Long myfilter (DWORD dwexceptioncode)
{
If (dwexceptioncode = exception_access_violation)
Return exception_execute_handler;
Else
Return prediction_continue_search;
}

(3) Global Expansion
First, let's take a look at the basic process of global expansion (This flowchart comes from reference [1]):

Next, let's look at a global expanded instance (source code globalunwindsample. cpp): code:

# Include <iostream. h> # include <windows. h> static unsigned int nstep = 1; void function_ B () {int X, Y = 0; _ Try {x = 5/y; // raise exception }__ finally {cout <"Step" <nstep ++ <": Execute the Finally block content of function_ B" <Endl ;}} void function_a () {__ try {function_ B () ;}__ finally {cout <"Step" <nstep ++ <": execute function_a's finally block content "<Endl ;}long mycomputefilter () {cout <" Step "<nstep ++ <": execute the main exception filter "<Endl; return exception_execute_handler;} int main () {_ Try {function_a ();} _ partition T (mydeletefilter ()) {cout <"Step" <nstep ++ <": content of blocks t of execution main" <Endl ;}return 0 ;}/ * output result: step 1: Execute the exception filter of main Step 2: Execute the Finally block content of function_ B Step 3: execute the Finally block content of function_a Step 4: Execute the contents of blocks t of main */

The execution process of this program is as follows:

(4) pause Global Expansion
If an exception occurs in the program and the try block corresponding to exception_execute_handler has been found, the system expands globally. Normally, the system will execute all finally processes within the try block, and then execute the exception handling process corresponding to the try block. However, if a return is put in a Finally, global expansion can be prevented.

3. unhandled exceptions (top-level Exception Handling)
When an exception occurs in the software and there is no corresponding exception handling program in your program, an unhandled exception is formed. At this time, the system will pop up an exception prompt dialog box, and you can end the process.
The displayed exception dialog box shows how this function is implemented in the unhandledexceptionfilter. When the process and thread are started, the system will install a top-level Exception Handling try-Wait T structure, as shown below:

Baseprocessstart is used for the main thread of the process, while basethreadstart is used for other threads. When an exception occurs, if no exception handler exists in the program or all returns prediction_continue_search, The unhandleexceptionfilter API is automatically called.

Iii. Introduction to Seh-related data structures
1. prediction_pointer Structure

2. prediction_record Structure

3. exceptoin_registration Structure

4. Exception Handling Link Structure

IV. Implementation of VC ++ compiler-level seh
1. Abnormal frame of VC Extension

2. Abnormal frame STACK layout of VC

3. Two instance programs: display abnormal frame information (for details, see showexcptframe1.cpp and showexcptframe2.cpp)
It doesn't matter if you are not familiar with the above structure. We will further understand it through the instance below. Code:

/// Display scopetable information // void sehshowscopetable (pvc_exception_registration PVC excrec) {printf ("frame: % 08x handler: % 08x PREV: % 08x scopetable: % 08x \ n ", \ PVC excrec, PVC excrec-> handler, PVC excrec-> Prev, PVC excrec-> scopetable); pscopetable pscopetableentry = PVC excrec-> scopetable; For (INT I = 0; I <= PVC excrec-> trylevel; I ++) {printf ("scopetable [% u] prevtrylevel: % 08x" "filter: % 08x _ exc EPT: % 08x \ n ", I, pscopetableentry-> previoustrylevel, pscopetableentry-> lpfnfilter, pscopetableentry-> lpfnhandler); pscopetableentry +;} printf (" \ n ");} /// display abnormal frame information // void sehshowexcptframes () {pvc_exception_registration PVC excrec; // obtain the first address of the abnormal frame chain and save it in PVC excrec _ ASM mov eax, FS: [0] _ ASM mov [PVC excrec], eax // traverses the exception frame chain while (unsigned) PVC excrec! = 0 xffffffff) {sehshowscopetable (PVC excrec); PVC excrec = (pvc_exception_registration) (PVC excrec-> PREV );}}

Nested exception structure Example 1:

Output result:


Nested exception structure Example 2:

Output result:

4. instance analysis and features (comparative analysis, pay attention to the relationship between structure examples and results)

[1] the preceding two results have four abnormal frames.
[2] their last two abnormal frames are consistent, but only the first two abnormal frames are changed.
[3] It is both a two-valued function call, mainfunction. Each call creates an exception frame. The first frame indicates the inmost abnormal block, that is, the abnormal frame of the function (compared with the function that displays the abnormal frame information), the second frame represents the abnormal frame of the main function.
[4] The number of items in the scopetable field is related to the number of abnormal blocks in the function. In the function in the example, there are three nested exception blocks. Therefore, there are three items in the first scopetable frame; the function in example 2 contains four exception blocks, so there are four items in scoptable In the second frame.
[5] First, let's look at Example 1. The three exception blocks in the function are nested, so in scopetable [2], prevtrylevel = 1, indicates that the index of the current abnormal block in the frame is 2, and the index of the outer abnormal block adjacent to it is 1. The exception filter address of this abnormal block is filter: 00401204, the address of the callback function for exception handling is _ 0000t: 00401207. Therefore, the three items in scopetable In the first frame of Example 1 form a linked list (this is also better understood: nesting of three exception blocks ). Let's take a look at Example 2 and check whether two linked lists are formed in the first frame. Here, the meaning of prevtrylevel in scoptable should be clear. If you are not quite familiar with this part, you can add or modify abnormal blocks in the program, or add several more layers of function calls, and then observe and analyze the output results.
[6] I wonder if you have found a handler in the exception_registration structure, and an lpfnhandler in scopetable (the _ handler T in the output result of the above example ), these two are the addresses of the exception handling callback functions. What are the relationships and differences between them? In this example, the handler address of the first three frames is 004014b0, why?
This is not difficult to answer. The lpfnhandler in scopetable is used for user-defined exception handling functions, while the handler in prediction_registration is used for the system's default exception handling program, that is, the top-level Exception Handling callback function.
[7] I have analyzed only two of the four frames. The role of the last two frames will be explained later.

5. Top-level Exception Handling in VC
Do you still remember the baseprocessstart and basethreadstart functions mentioned when I introduced the second part of the unhandled exception. When the main/sub-thread is started, the system places the entire thread in an exception block, that is, the top-layer Exception Handling body. The fourth frame in the above two examples shows the exception frame.

By default, the entry points of the VC program are implemented by the Runtime library functions maincrtstartup and winmainaincrtstartup. (If you are not familiar with this, see [5] For details.) again, the main and winmain (default) user program portals to be called are placed in the exception handling body. The third frame of the two examples that show the exception frame above comes from here.

For these two entry functions, the CRT has the corresponding source code, which is simplified as follows:


Now we can summarize the example of the exception block structure in the VC compiler by default (that is, the imported seh is not displayed in our program:

The baseprocessstart and winmaincrtstartup functions are not fixed and need to be determined based on the actual situation. This is just an example.
The third and fourth exception frames left over in the previous section have been resolved.

6. VC search exception handling process
When introducing the third part of Seh-related data structure, we have already introduced the structure of the exception handling chain, but for exception handling in VC, the exception frame extension includes the introduction of the scopetable structure to support nested exception structures. Therefore, when an exception occurs, the process of finding the corresponding exception handler is more complicated. The VC search exception handler process is as follows:


[References]
[1]. Windows core programming Jeffrey Richter, published by Mechanical Industry Press
[2]. A crash course on the depths of Win 32 & reg; structured exception handling

Http://www.microsoft.com/msj/0197/Exception/Exception.aspx

[3]. Windows 2000 Internal encryptor Machinery Industry Press
[4]. Windows exception handling process sobeit
Http://www.nsfocus.net/index.php? Act = magazine & Do = view & Mid = 2471
[5]. Small knowledge points for compiling and running programs in VC
Http://fmddlmyy.home4u.china.com/text3.html

Uploaded attachment


Seh-source.rar (, 0,196 downloads)
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.