How to achieve an abnormality in C ++ compiler 4

zhaozj2021-02-16  48

C and abnormal 2

Figure 5 shows the content of the function information (FUNINFO) structure. Note that the name of the structure may be different from the actual name used by the VC compiler, and I only show the relevant members in the figure, and the unwind Table member in the structure I will talk about it in the next section.

When an exception is generated, the exception handle has to look for the Catch block in the function, first it is to know that this abnormality in the function is not included in a TRY block. If the function does not have a TRY block at all, the exception handle is returned from the function, otherwise, the exception handling is found from all TRY blocks that contains the block containing this statement.

First, let's take a look at how to find this associated TRY block. When compiling, the compiler is assigned to each TRY block a start ID and an end ID, and it is easy to find these IDs through the Funcinfo structure. Refer to Figure 5. The compiler generates the Tryblock data structure for each TRY block in the function.

In the previous chapter, I have already said the vc extended Exception_registration structure, there is a member called ID in this structure. This structure is placed on the function frame, referring to Figure 4. When an exception is generated, the exception handle is obtained from the stack from the stack, and then detects that this ID is one of the two IDs equal to the TRY block, or the value ranges between the start and end ID. If the above conditions are satisfied, then the abnormal statement is in this TRY block, if not, the exception handling looks for the next TRY block in the TryblockTable.

Who wrote these values ​​in the stack? What should this value? The compiler fills in the appropriate statement in different locations of the function to update the ID of the current frame, reflecting the current operating state by such means (translation:

For example, a code:

BOOL E1 (FarProc P)

{

Try {return (* p) ();

Catch (...) {Printf ("Exception / R / N"); Return False;}

}

This is like compiling

VAR_10 = DWORD PTR-10H; Data Definition

VAR_C = DWORD PTR-0CH; Data Definition

VAR_4 = DWORD PTR-4; Data Definition

Push EBP; Caller's EBP

MOV EBP, ESP

Push 0FFFFFFFH; this is ID

PUSH OFFSET LOC_401320; HANDLE

Mov Eax, Large FS: 0

PUSH EAX; Prev, these four components in the stack have made structures Exception_Registration

Mov Large FS: 0, ESP; then register now of Exception_Registration on FS: 0

Push ECX

Push EBX

PUSH ESI

Push EDI

MOV [EBP VAR_4], 0; this is to turn the ID from 0xfffffffffff, which is the appropriate location in the author

MOV [EBP VAR_10], ESP; Keep ESP, see Figure 4

Call [EBP ARG_0]; call function

MOV ECX, [EBP VAR_C]

MOV LARGE FS: 0, ECX; Restore FS: 0 value is prev, and the return value of the call function (* p) () is placed in Eax, so the ECX register is used.

POP EDI

POP ESI

POP EBX

MOV ESP, EBPPOP EBP; Restore EBP

Retn

)

For example, the compiler adds a statement to the TRY function block, and writes the starting ID of the TRY function block to the stack frame of the function.

When an exception handler is abnormal, a Try function block contains a statement that generates an exception, which checks if this TRY function block has a Catch block to capture this anomalies via the TryCatch table. Note that in the nested TRY function block, the exception generated by the inner TRY function block is also in the range of the outer TRY function block. In this case, the abnormality is processed first looking for the inner layer Catch block. If you are not found, you can go to the outer TRY function block. When generating a tryblock table, VC places the innermost Tryblock structure before the outer TRYBLOCK.

How do you know (from the structure of Catch block) A Catch block can't capture the current exception? It is the type of an abnormal object by comparing the parameters of the Catch block.

Abnormal H and E, which caught Catch blocks are exactly the same type, and the abnormality generated will be captured. Therefore, the abnormality handle has to dynamically compare the type of parameters. However, in general, C or similar C is not easy to determine the type of parameters at runtime (the translation: c is similar to the assembly, seeing the length, who knows what type it in the source code) . To do this, a class called Type_info is defined, which is written in the standard header file to describe the type of variable runtime. The second member of the CatchBlock structure (Figure 5) is a pointer to the Type_info structure that represents the type of time of the CATCH block parameters. The TYPE_INFO class is overloaded == operator, used to determine whether the two types are not exactly the same type. Therefore, all exception processing must do this comparison (call == operator overload function) to confirm that the type_info of the catchblock parameter and whether the generated TYPE_INFO is equal to it, thus determining that the current Catch block can capture the current exception.

Abnormal handling from the Funcinfo structure knows the parameters of CatchBlock, but how do you know that the current exception type_info, when the compiler encounters such a statement

Throw e ();

It creates an ExcPt_info structure for this throwing exception, referring to Figure 6. Note that the name may differ from the VC compiler, and I only list the relevant items. As shown, the exception Type_info can be accessed by the EXCPT_INFO structure. Sometimes, the abnormality handles the abnormality (when Catch block is completed), it may also need to copy an abnormally (before calling the Catch block), in order to help exception processing, the compiler produces an exception, copy constructor and take A function of an exception object (via the EXCPT_INFO structure)

If the parameter of the Catch block is a base class, the exception generated is its derived class, and the exception handling should still call this Catch block when an exception is generated. However, comparing these two types (base classes and derived classes) will return False because the two types are not the same type. Whether it is a member function provided by the Type_info class or an operator, it cannot be judged that the two classes are not another subclass. However, in this case, the abnormality processing does not capture such an exception. How did this do it? In fact, the compiler produces more information for this exception. If the exception class is derived from other classes, ETYPEINFO_TABLE (in the structure EXCPT_INFO structure) contains ETYPE_INFO (extended type_info, my name) pointer points to all parent classes, such exception handling the Type_info and Catch block of the CatCh block All type_info of the parameters (you and your own base class TYPE_INFO). As long as there is a match success, the Catch block will be executed. Before I summarize this section, there is at least one problem, that is, how is the abnormal handle, where is the current unusual EXCPT_INFO? I will answer this question below.

VC compiles the Throw statement into and similar statements below:

// throw e (); // compiler generates Excpt_info structure for E.

E E = E (); // Create Exception on the Stack

_CXXTHROWEXCEPTION (& E, E_EXCPT_INFO_ADDR);

_CXXTHROWEXCEPTION passes control to the operating system (through software interrupt, see function raiseexception) while passing two parameters. When the operating system is ready to call an exception callback function, packed the two functions into the structure_exception_record. Then, the operating system finds the first Exception_Registration structure of the exception handle of FS: [0], and calls the Handle in the structure. Pointer to the Exception_Registration is the second parameter for exception processing. Again, every function in VC creates its own Exception_registration structure on its own frame, and registering this structure to the system. The second parameter is important to exception processing, and it can find members like ID (no ID can be determined). This parameter can also make the exception handle the stack frame of the function (this is useful to clear this frame variable), and you can find more Exception_Registration nodes down (this is useful for clearing the stack). The first parameter is a pointer to the _exception_record structure, which can find the pointer of the abnormal object and the EXCPT_INFO structure by its exception handling. The return value for exception processing is defined in Excpt.h

(Translation:

Typedef enum _EXCEPTION_DISPSITION {

ExceptionContinueexecution,

ExceptionContinueSearch,

ExceptionnestedException,

ExceptionCollidedunwind}

Exception_disposition;)

Exception_Disposition (* handler)

_Exception_record * ExcRecord,

Void * EstablisherFrame,

_Context * ContexTrecord,

Void * dispatcherContext);

You can ignore the last two parameters. The return value of the abnormality processing is an enumeration (Exception_DisPosition type). In the front we have said, if the exception handle cannot find the Catch block, it returns ExceptionContinuesearch to the operating system. Other less important information in structure _exception_record, this structure is defined in Winnt.h: struct _exception_record

{

DWORD EXCETIONCODE;

DWORD EXCEPTIONFLAGS;

_EXCEPTION_RECORD * EXCRECORD;

PVOID EXCEPTIONADDRESS;

DWord NumberParameters;

DWORD EXCETIONINFORMATION [15];

EXCEPTION_RECORD;

The number of ExceptionInformation arrays and the type of entry is determined by ExceptionCode. If ExceptionCode indicates an exception is a C exception (ExceptionCode is 0x06d7363, such a case occurred if an exception is generated via throw), then the ExceptionInformation array contains pointers to the exception object and the Excpt_info structure. And other abnormalities, basically there is no entrance. Other abnormalities have 0, access rejection, etc., they can find their corresponding values ​​in Winnt.H.

An exception handling what action taken when the Exception_Record structure of ExceptionFlags is decided. If this value is EH_UNWINDING (defined in Except.inc), prompt the exception handling Clear Stack is going on, at this time, the exception handle should clear the function stack frame and return. Clear Function Frames include such actions, find all local variables that have not been released during an abnormality, and then call their destructor. This will continue to discuss this next section. Otherwise, the exception handle has to continue to find the matching catch block in the function, and then call the found Catch block.

转载请注明原文地址:https://www.9cbs.com/read-26551.html

New Post(0)