Structure exception and C ++ exception

Source: Internet
Author: User

Comparison between C ++ and Windows structure exceptions

Windows structure exceptions have the following features:

1. It uses the _ try, _ partition T, _ finally, and _ leave keywords and RaiseException APIS;

2. It is supported by Windows, so it is not suitable for other operating systems

3. It does not parse C ++ objects

Note: If a C ++ object exists in a function with a Windows structure exception, the compiler will issue

Output: error C2712: Cannot use _ try in functions that require object unwinding error.

For example:

Void fun ()

{

CObject object; // error! The C ++ object cannot be parsed due to a structural exception.

_ Try {

...

}

_ Partition T (...){

...

}

}

4. It is thrown as a result of a hardware exception (for example, an illegal access or division by zero) or an operating system exception.

It can also be thrown as the result of the raiseexception function;

C ++ exceptions are characterized:

1. Use keywords such as try, throw, and catch;

2. It processes the parsing of C ++ objects;

3. It is thrown as the result of the throw statement;

Note: MFC provides the third exception handling mechanism. It uses several exception handling macros. These macros are also compiled into C ++ exceptions, so there is no need to use them in new code! Differences in MFC programming

Common objects are derived from c0000t. Most of the MFC exception handling objects are dynamically allocated. Therefore, when they are captured, they must be deleted-

The llwndproc function is captured and deleted.

Because the C ++ exception cannot handle hardware and operating system exceptions, You need to convert the structure exception

C ++ exception.

How to convert a structure exception to a C ++ exception

Visual c ++ allows you to use the _ set_se_translator function to convert a structure exception to a C ++ exception.

# Include <eh. h>

Class csehexception

{

Public:

Csehexception (uint code, pexception_pointers pep)

{

M_exceptioncode = code;

M_exceptionrecord = * pep-> predictionrecord;

M_context = * pep-> contextrecord;

Asserte (m_exceptioncode = m_exceptionrecord.exceptioncode );

}

Operator unsigned int () {return m_exceptioncode ;}

Uint m_exceptioncode;

Prediction_record m_exceptionrecord;

Context m_context;

};

// Structured exception to C ++ abnormal Converter

Void cdecl translatesehtoce (uint code, pexceptionpointers pep)

{

Throw csehexception (Code, Pep );

}

Int apientry winmain (......)

{

// Install the abnormal Converter

Setse_translator (translatesehtoce );

}

Note that the exception converter works on the basis of each thread, so you need to install a converter for each thread. This exception converter has a side effect. You will see two exception tracking messages in the debug tag of the output window: one for the original structure exception, the other is for the converted C ++ exception. After the exception converter is used, you can capture structure exceptions like C ++ exceptions.

Compilation options related to exceptions

First look at the following functions:

Void testbugexception ()

{

Try {

Int * pint = 0;

* Pint = 42;

}

Catch (...) {

MessageBox (0, ", 0, MB_ OK );}}

Obviously, the above Code will generate a structured exception, but the exception is handled using a C ++ exception

Mechanism, will this exception be handled? The answer is that the compiling environment depends on the default situation of VC.

The exception is handled in the debug version, but not in the release version. For VC,

A c ++ exception can only be thrown by a throw statement or a throw statement is contained in the called function. Any other

C ++ exceptions cannot be received in all the code, so the debugger will think that there is no C ++ exception in the try Statement (

Because there is no throw Statement), the unwanted Exception Handling Code is removed in the release version to optimize the program.

The exception described above is called the synchronization exception model, which is set by the/GX compilation option and is the default setting of VC6. In contrast to the asynchronous exception model, any command is used to generate

Exception mechanism. The asynchronous exception model is set by the/EHA compilation option. That is, the/EHA option can make C ++ different

The regular mechanism captures structural exceptions.

There is also a compilation option:/EHS, which is also a synchronization exception, but unlike/GX,/GX indicates

Assume that the function of the extern "C" does not throw a C ++ exception. Extern "C" functions are generally compiled by C functions, so they do not throw C ++ exceptions, and of course there are exceptions.

If your program uses the exception mechanism but does not use one of the exception handling compilation options, a warning message is generated during compilation: warning C4530.

Let new and malloc throw an exception

By default, new and malloc do not throw errors. You can use

_ Set_new_handler installs a processor so that new throws an exception for the error. By calling

_ Set_new_mode enables malloc to use the same processor.

# Include <new. h>

Int NewHandler (size_t size)

{

Throw exception ("xxxx ");

}

Int main ()

{

_ Set_new_handler (NewHandler );

_ Set_new_mode (1 );

}

_ Set_new_mode (1) indicates that malloc uses the new processor.

Abnormal Performance

When an exception is thrown, the function call chain will trace back and search for such exceptions that can be handled.

. Of course, if a proper processor is not found, the process will end. If the processor is not found

The call stack will be released, all automatic (local) variables will be released, and the stack will be sorted as different

The context-related device of the processor. Therefore, the exception overhead is maintained by an exception processor directory and an active automatic variable table (it requires additional code, memory, and runs regardless of whether the exception is thrown or not ),

The function call chain search, automatic variable parsing, and stack adjustment must be added (it must be executed only when an exception is thrown.

When exceptions are rarely thrown, the overhead of exceptions is not large, and the performance may be improved.

See the following code:

// Judge the pointer instead of using an exception

Int check (int * pInt1, int * pInt2, int * pInt3)

{

If (pInt1! = 0 & pInt2! = 0 & pInt3! = 0)

{

......

}

Else

Return-1;

}

// Use exception. If the probability of a parameter being NULL is low, the efficiency of using exceptions is higher!

Int check (int * pInt1, int * pInt2, int * pInt3)

{

Try {

...

}

Catch (...)

{

Return-1;

}

}

Exception Handling requires a lot of extra operations, making it not suitable for frequently Running code (such as in a loop ).

In more detail, catch blocks have some overhead, but try blocks have very little overhead. Therefore, only when exceptions are thrown

Usually, there will be a lot of abnormal operation overhead.

When to throw an exception

First, describe when the return value is applicable,

1. Used for non-error status information

2. errors that can be ignored without any problems in most cases

3. It is used to make it easier to generate errors in the loop. Because of the extra overhead of exceptions, it is a better choice to use the returned values for better performance.

4. Errors used in the intermediate language module, such as COM components, must be returned rather than exceptions.

When an exception is thrown, it should be a function error that can prevent the program from running normally. When a function cannot return values, such as constructor or overloaded operator '=', an exception is thrown. However, you should note that you cannot throw an exception from the destructor, because the exception can prevent the call of Delete, so there will be resource leakage:

Delete pobject

Equivalent:

Pobject-> ~ Cobject ()

Operator Delete (pobject)

Therefore, the operator Delete call will be skipped if an exception is thrown in the Destructor!

Usage exception Specification

To handle exceptions, you need to know which type of exceptions a function can throw. Function throw

Is considered part of the interface protocol, and its parameters and return values are the same.

C ++ provides exception specifications. See the following function prototype:

Void normalfunction ();

Void nothrowfunction () Throw ();

Void throwfunction () Throw (cexception );

Among them, normalfunction can throw any exception because it has no exception specification, while nothrow-

Function can not throw an exception. The exception specifications of these two functions seem completely different. Finally,

ThrowFunction can throw any exception object derived from Cexption.

Exception specification problems:

1. Incomplete exception specifications: If the thrown exception is not derived from the exception termination class, the thread calls unexpected and ends the process by default. To create a complete Function Specification, you need to find all the unprocessed exceptions thrown by the function and all the functions called by this function (if these exceptions have been processed in this function, they are not considered ).

2. The exception specification will not be checked during compilation, and the following code will not be warned during compilation:

Void Funtion () throw () // specification: No exception is thrown

{

Throw CException; // but an exception is thrown.

}

3. It cannot be mixed with a template. Because the template parameters can be of any type, you cannot know what exceptions can be thrown by member functions of this type;

4. If you use an exception (catch can catch a structured exception), in fact, any function can throw a converted structure exception.

1. Non-mfc c ++ exceptions should be captured by reference (catch T & e )). Use reference capture

When an exception is obtained, you do not need to delete the exception object (because exceptions captured by reference will be transmitted in the stack ), and it retains polymorphism (so the exception object you capture is exactly the exception object you throw ). You need to delete the object to capture exceptions using pointers.

2. MFC exceptions should be captured through pointers. Because they are allocated from the heap, after you handle the exception,

You need to call the Delete member function as follows:

Catch (CfileException * e)

{

E-> Delete (); // do not use delete because some MFC exceptions are created as static objects.

}

You cannot use the omitted capture processor to capture an MFC exception because it causes a memory leak.

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.