Handle errors and exceptions

Source: Internet
Author: User
Error and Exception Handling reference

The following thesis gives a good introduction to some issues about compiling robust general-purpose components:
D. abrahams: ''exception safety in generic components', composed of M. jazayeri, R. loos, D. musser (eds .): Generic programming, Proc. of a dagstuhl seminar, lecture notes on computer science. volume. 1766 Publishing

Guide

When is the usage abnormal?

A simple answer is: "When the semantic and performance requirements of exceptions are appropriate ."

A frequently-mentioned method is to ask yourself: "Is this an exception (or unexpected ?" This method seems attractive, but it usually only leads to incorrect answers. For a person, the situation is "abnormal", but "normal" for another person: when you really think about this sentence carefully, you will find that you cannot differentiate it. This sentence cannot help you at all. After all, if you check an error condition, it means you think it will happen. Otherwise, your check is just junk code.

A more suitable question is: "Do I need to expand the stack here ?" As Exception Handling almost always means slower than normal process code, you should also ask yourself: "is the cost of stack expansion affordable ?" For example, a computing task that is being done takes a long time and periodically checks whether the user has pressed the cancel key. If an exception is thrown, the operation can be canceled elegantly. On the other hand, it may be inappropriate to throw and capture processing exceptions in the internal loop of this computation, which may cause serious performance degradation. The preceding content includes the following principle: for time-critical code, throwing an exception is an "exception" approach, rather than a regular one.

How to Design exception classes?

1. The exception class is derived from STD: exception. Except for some very rare cases, such as not being able to afford the overhead of functions. It is reasonable to use STD: exception as the exception base class. When it is widely used, it will allow programmers to catch any exceptions without using catch (...). more about catch (...).
2. Use virtual inheritance. This profound insight comes from Andrew Koenig. when an exception is thrown, it is derived from multiple base classes and these base classes share the same part, the catch point will encounter ambiguity, virtual inheritance from the exception base class can prevent such ambiguity:
# Include <iostream>
Struct my_exc1: STD: exception {char const * What () const throw ();};
Struct my_exc2: STD: exception {char const * What () const throw ();};
Struct your_exc3: my_exc1, my_exc2 {};

Int main ()
{
Try {Throw your_exc3 ();}
Catch (STD: exception const & E ){}
Catch (...) {STD: cout <"whoops! "<STD: Endl ;}
}
The above program prints "whoops", because the C ++ runtime cannot decide to use the exception instance to match the first catch. (BALD: I suggest you do not use multiple inheritance here)
3. Do not embed STD: string objects or other copy structures that may throw exceptions to data members and base classes. If an exception is thrown at the preceding vertex, STD: Terminate () is called directly (). it is also a bad idea to make the default constructor of the base class or data member throw an exception. You were planning to report an exception through a throw expression that contains the object structure, the program ended without any need:

Throw some_exception ();

When an exception copy occurs, there are several methods to avoid copying string objects, such as embedding a fixed-length storage area in the exception object, or managing strings through reference counting. However, before using these methods, consider the next one.
4. format the information returned by what () only when necessary. Formatting is a typical memory-related operation that may throw an exception. It is best to postpone formatting until the stack is expanded, because the stack expansion may release some resources. It is a good idea to use catch (...) blocks to protect the what () function, so that you can return when an exception is thrown during formatting.
5. Do not care too much about what () information. In exception throws, this is a good opportunity for programmers to give error information, but you may not be able to combine the relevant information into a form that users can understand. Internationalization is a typical situation. Peter DIMOV provides a good suggestion: Create a table with an error message formatted and use the string of what () as the key of the table. When a standard library throws an exception, if we can only obtain its standard what () string ......
6. Expose the information related to the error in the public interface of the exception class. What () returns fixed information means you ignore the exposed information, and the user may need to provide relevant information. For example, if you want to report a numeric range error, the code that reports the error should be able to include the variable value that causes the problem through the public interface of the exception. If you present these numbers in text in what (), it will be a tough time for programmers who need to process more (or less) based on information.
7. If possible, make your exception class immune to the two Destructors. Several Popular compilers occasionally destroy abnormal objects twice. If you can take measures to defend against hazards (for example, setting the released pointer to zero), you can make the code more robust.

How to deal with mistakes made by programmers?

As a developer, If I violate a certain precondition of the used library, I do not want to expand the stack. What I want is core dump or equivalents-a method that can precisely check the state of the program at the point where the problem occurs. This usually means assert () or something similar.
Sometimes it is necessary to provide users with robust APIs that can cope with arbitrary misuse, but this usually requires a high price. For example, a common requirement is to track every object used by the customer to Verify validity. If you need such protection, it is usually implemented by encapsulating a layer on a simple API. Although you are careful, APIs with strong commitments can only defend against some, rather than all misuse that may lead to disasters. Customers are also beginning to rely on those protections, and the ones they depend on will also grow to areas that cannot be protected by interfaces.
Note for Windows developers: When you use assert (), most Windows compilers actually throw an exception and are intercepted locally. Unfortunately. In fact, the intercepted errors are often block access failures or division by zero errors. This is a problem when you use JIT (Just In Time) debugging, which means that the exception Stack has been expanded before the debugger is awakened, because catch (...) This exception will be caught. In fact, this is not a C ++ exception. Fortunately, there is a little-known simple way to deal with it:
Extern "C" Void straight_to_debugger (unsigned int, exception_pointers *)
{
Throw;
}
Extern "C" void (* old_translator) (unsigned, exception_pointers *)
= _ Set_se_translator (straight_to_debugger );
This method cannot cope with situations where a structured exception is thrown in a Catch Block (or a function called by the Catch Block), but it can solve the problems caused by most JIT operations.

How to handle exceptions?

Simply not handling exceptions is generally the best way to handle exceptions. If you allow exceptions to traverse your code and perform cleanup in the destructor, the code will be cleanup.

Try to avoid catch (...)

Unfortunately, other non-Windows operating systems will involve non-C ++ exceptions (such as thread suspension) in the C ++ exception mechanism. Moreover, sometimes there is no hack solution similar to the _ set_se_translator mentioned above. We usually perform reasonable operations in the Destructor or catch block to maintain the system's variant, which is usually safe. However, catch (...) will also capture unexpected system notifications. At this time, it is impossible to handle exceptions like common C ++, and the conventional approach is no longer secure.

After a long debate in the news group, despite reluctance, I still have to admit Hillel y. sims point of view: unless all operating systems fix the previous issue, all exceptions should inherit from STD: exception, when everyone adapts to catch (STD: exception &) instead of catch (...) the world will be even better.

Sometimes catch (...) is the most suitable option, even if you do not consider poor interaction with the operating system. If you do not know what exceptions will be thrown and you must stop the stack expansion, this may be your only way out. A typical scenario is cross-language.

Copyright David Abrahams 2001-2003. All rights reserved.

Original article link

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.