C + + exception handling

Source: Internet
Author: User
Introduction

exception, so that a function can throw an exception when it finds an error that it cannot handle, and that the caller can handle the problem directly or indirectly. While traditional error-handling techniques check for a local problem that cannot be handled:

1. Terminate the program (for example, Atol,atoi, enter NULL, will produce a segment error, causing the program to exit unexpectedly, if there is no core file, the person looking for the problem will be crazy)

2. Returns a value that represents an error (many system functions, such as malloc, insufficient memory, allocation failure, return null pointer)

3. Return a legal value that keeps the program in some sort of illegal state (most pit-daddy stuff, some third-party libraries really do)

4. Invoke a function that is ready to be used in case of "error".

The first case is not allowed, the unconditional termination of the application of the library can not be used in the machine can not be in the program. The second case, more commonly used, but sometimes inappropriate, such as the return error code is int, each call to check the error value, very inconvenient, but also easy to double the program size (but to precisely control the logic, I think this is a good way). In the third case, it is easy to mislead the caller, in case the caller does not check the global variable errno or otherwise checks the error, it is a disaster, and this method does not work well in concurrent situations. As for the fourth situation, I feel less use, and the callback code should not appear more.

Using exceptions, the error and processing are separated, the library function throws an exception, the caller catches the exception, the caller can know that the Program function library call error, and to deal with, and whether to terminate the program is in the caller's hand.

However, error handling is still a difficult task, and C + + 's exception mechanism provides programmers with a way to handle errors, allowing programmers to handle errors in a more natural way.

Introduction to Exception Combat

Let's say we write a program that converts two strings entered by the user into integers and outputs, which is what we'll write.

Char *str1 = "1", *str2 = "2", int num1 = Atoi (str1), int num2 = atoi (str2);p rintf ("Sum is%d\n", NUM1 + num2);

Assuming that the user entered Str1,str2, if both str1 and str2 are integer-type strings, this code works correctly, but the user's input may be mistakenly manipulated and illegal characters are entered, such as

Char *str1 = "1", *str2 = "a", int num1 = Atoi (str1), int num2 = atoi (str2);p rintf ("Sum is%d\n", NUM1 + num2);

This time the result is 1, because atoi (STR2) returns 0.

If the user input is this:

Char *str1 = "1", *str2 = null;int num1 = atoi (str1), int num2 = atoi (str2);p rintf ("Sum is%d\n", NUM1 + num2);

Then this piece of code will have a segment error, the program exits unexpectedly.

Atoi I think is a more dangerous function, if in an important system, the caller does not know, passed in a null character, the program is abnormally exited, resulting in service interruption, or the passing of illegal characters, the result returns 0, the code continues to go on, in the complex system to locate the problem is really not easy.

So the more appropriate way, we use abnormal treatment to transform a safe Atoi method, called Parsenumber.

Class Numberparseexception {};bool isnumber (char * str) {     using namespace std;     if (str = = NULL)         return false;     int len = strlen (str);     if (len = = 0)         return false;     BOOL Isanumber = false;     char ch;     for (int i = 0; i < len; i++) {         if (i = = 0 && (str[i] = = '-' | | str[i] = = ' + '))             continue;         if (IsDigit (Str[i])) {            Isanumber = true;         } else {           isanumber = false;           break;         }     }     return isanumber;} int Parsenumber (char * str) throw (numberparseexception) {    if (!isnumber (str))        throw numberparseexception ();    return atoi (str);}

In the code above, Numberparseexception is a custom exception class, when we detect when the incoming STR is not a number, throw a number conversion exception, let the caller handle the error, which is more than passing in a null string, resulting in the end of the paragraph error program is much better, The caller can catch this exception, decide whether to end the program, or pass in a non-integer string, return 0 is better, the program error, but continue to silently execute.

So the code we wrote earlier could be modified as follows:

Char *str1 = "1", *str2 = NULL;    try {        int num1 = Parsenumber (str1);        int num2 = Parsenumber (str2);        printf ("Sum is%d\n", NUM1 + num2);    } catch (numberparseexception) {        printf ("Input is not an integer \ n");    }

The result of this code is to print out "input is not an integer". Assuming this code is running in a game statistics system, the system needs to regularly from a large number of files to count the number of users into the game Channel 1 and Game Channel 2 times, STR1 represents into the game Channel 1 times, STR2 represents the number of channels to enter 2, If an exception is not used, when the input is NULL the program causes the entire system to be down, and when the input is an illegal integer, the results are all wrong, and the program still silently "executes correctly".

The input is illegal and throws numberparseexception, even if the caller does not consider the input to be illegal, for example:

Char *str1 = "1", *str2 = "n";    int num1 = Parsenumber (str1);    int num2 = Parsenumber (str2);    printf ("Sum is%d\n", NUM1 + num2);

Even if the caller is careless, there is no catch exception, the program will throw Numberparseexception, the program goes down, will leave the Coredump file, the caller through the "GDB program name coredump file", to see the program down the stack, you know the program is running, There is an illegal integer number, then he will soon know the problem, will learn, and change the above code to

Char *str1 = "1", *str2 = NULL;    try {        int num1 = Parsenumber (str1);        int num2 = Parsenumber (str2);        printf ("Sum is%d\n", NUM1 + num2);    } catch (numberparseexception) {        printf ("Input is not an integer \ n");         Print the path of the file, line number, STR1,STR2 and other information enough to locate the problem itself     }

This way, the next time a problem occurs, the caller can locate the problem, which is the exception of the error handling, the wrong Discovery (Parsenumber) and error processing (game statistics code) separate.

This article introduces exception throws and captures, as well as unusual usage scenarios, and then begins to step through the C + + exceptions.

Description of the exception

The set of exceptions that functions and functions may throw is valuable as part of a function declaration, such as

void f (int a) throw (X2,X3);

Indicates that f () can only throw two exception x2,x3, as well as exceptions that derive from these types, but do not throw other exceptions. If the F function violates this rule and throws an exception other than x2,x3, such as X4, then when the function f throws a X4 exception,
is converted to a std::unexpected () call, the default is to call Std::terminate (), which is usually called abort ().

If the function is not described with an exception, it is assumed that he may throw any exception. For example:

int f ();  May throw any exception

Functions with any exceptions can be represented by a blank table:

int g () throw (); Does not throw any exceptions

Catching exceptions

The code that catches the exception is generally as follows:

try {    throw E ();} catch (H h) {     //When can we get here?}

1. If H and e are the same type

2. If h is the base class for E

3. If both H and e are pointer types, and 1 or 2 are valid for the type they reference

4. If both H and e are reference types, and 1 or 2 of the types referenced by H are established

In principle, exceptions are duplicated when thrown, and the last exception we catch is just a copy of the original exception, so we should not throw an exception that does not allow a copy to be thrown.

In addition, we can add a const to the type used to catch the exception, just as we can add a const to the function, restricting us from modifying the caught exception.

Also, if the exception is caught when H and e are not reference types or pointer types, and H is the base class of E, then the H object is actually h H = e (), and the last caught exception object H loses the additional carrying information of E.

Order of exception handling
The Parsenumber function we wrote earlier would throw Numberparseexception, which simply determines if the number throws an exception, but it is not considered, but this string represents an integer that is too large to overflow and throws an exception overflow.

Class Numberparseexception {};class overflow:public numberparseexception {};

Suppose our Parsenumber function has been detected as an integer overflow of strings, and in this case the overflow exception is thrown, then the exception capture code is as follows:

Char *str1 = "1", *str2 = NULL;    try {        int num1 = Parsenumber (str1);        int num2 = Parsenumber (str2);        printf ("Sum is%d\n", NUM1 + num2);    }     catch (Overflow) {        //handle Overflow or any exception derived by Overflow    }    catch (numberparseexception) {         // Handling numberparseexception exceptions that are not overflow    }

Exception organization This hierarchy is important for the robustness of code, because after a library function is published, it is not possible to not add new exceptions, just like our parsenumber, when the first release is just considering whether the input is an integer error, The second release considers whether a string entered as an integer is too large to overflow, and no new exceptions are added after a function is published, and almost all library functions are unacceptable.

If there is no exception hierarchy, when the function is added to the new exception description, we may have to modify the code, for each call to the function of the place to add the corresponding catch new exception statement, which makes you bored, it is easy for programmers to forget to add an exception to the list, resulting in the exception is not caught, abnormal exit.

With the exception of the hierarchy, after the function upgrade, for example, our Parsenumber added the Overflow exception description, the function caller only need to add catch (Overflow) in the calling scene of their own interest, and do the processing on the line, If you don't care about overflow errors, you don't even have to modify the code.

Uncaught exception

If the thrown exception is not captured, then the function std::terminate () is called, and by default it is called Abort, which is the correct choice for most users, especially in the phase of the wrong program error (calling abort will produce the Coredump file, The use of the Coredump file can refer to the blog "Learn to use Core Dump Debug program error").

If we want to ensure clean-up when an uncaught exception occurs, you can add a catch-all exception handler in main outside of all the exception handlers that really need attention, such as:

int main () {    try {        //...     }    catch (std::range_error) {        cerr << "range error\n";     } catch (Std::bad_alloc) {        cerr << "New run OU T of memory\n ";     } catch (...) {       //..     }}

This allows you to catch all exceptions except those that are constructed and refactored in global variables (the only way to get control is set_unexpected).
where catch (...) means catching all exceptions, and usually doing some cleanup work in the process code.

Re-throw

When we catch an exception and find that we cannot handle it, in this case, we will do what we can do locally, and then throw the exception again and let the exception be handled in the most appropriate place. For example:

void Downloadfilefromserver () {    try {          connect_to_server ();          //...     }       catch (networkexception) {           if (can_handle_it_completely) {               //handle network exception, such as re-connect           } else {                throw;       }}

This function is to download the file from the remote server, internal calls to connect to the remote server function, but there may be a network exception, if multiple reconnection cannot succeed, throw this network exception, let the upper processing.

The re-throw is represented by a throw without an operand, but if it is re-thrown and no exception can be re-thrown, terminate () is called;

Suppose Networkexception has two derived exceptions called Ftpconnectexception and Httpconnectexception, which is thrown when Connect_to_server is called Httpconnectexception , the call Downloadfilefromserver can still catch the exception httpconnectexception.

Standard exceptions

Here, you have basically used the exception, but if you are a function developer, and need to use the function to others, when using exceptions, will involve the custom exception class, but the C + + standard has defined a part of the standard exception, please reuse these exceptions as possible, the standard exception reference HTTP./ www.cplusplus.com/reference/std/stdexcept/

Although the C + + standard exception is relatively small, but as a function developer, as much as possible to reuse the C + + standard exception, as a function caller can spend less time to understand your custom exception class, better to call the function you developed.

Summarize

This article is simply from the exception of the use of the scenario, and then introduce the basic use of the exception, some advanced exception usage is not listed, detailed information can refer to C + + 's parent C + + programming language exception handling.

  • 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.