On the experience of C + + exception and error handling

Source: Internet
Author: User
Tags constructor error code error handling

The usual practice in lieu of try/catch/throw is to return a return code (sometimes called an error code), such as printf (), scanf (), and malloc (), which is how the caller tests the return value to determine whether the function was successful.

Although the return code technique is sometimes the most appropriate error-handling technique, it adds an annoying effect of unnecessary if statements.

Quality demotion: It is well known that conditional statements can contain approximately 10 times times more errors than other types of statements. So, at the same time, if you can eliminate conditional statements from your code, you'll get more robust code.

postponed to the market: because conditional statements are the fulcrum, and they relate to the number of test conditions in the white-box test, unnecessary conditional statements increase the total time of the test. If you don't walk through each point, your code will have instructions that have not been executed in the test until the user/customer discovers it, which is bad.

Increase development costs: the complexity of unnecessary control processes increases the search for bugs, fixes bugs, and tests work.

Therefore, using try/catch/throw produces less bugs, lower development costs, and faster time-to-market than reporting errors through return codes and if.

How do I handle the failure of a constructor?

Constructor does not have a return type, so it is not possible to return an error code. Throwing an exception is therefore the best way to mark a constructor failure.

If you are not or are unwilling to use an exception, here is a way. If the constructor fails, the constructor can bring the object into a "zombie" state. You can make an object as if it were dead by setting an internal state bit, even though technically it is still alive. Then add a query ("Inspector") member function so that the class user can check this "zombie bit" to determine whether the object is really alive or has become a zombie (i.e. a "Living Dead object"). You might want to have another member function to check this zombie bit, and execute a no-op (or more annoying, like abort ()) When the object is not really alive. It's not really pretty, but if you can't (or don't) use the exception, that's the best way to do it.

How do I handle the failure of a destructor?

Write a message to the log file. But don't throw an exception!

The rule of C + + is that you should never throw an exception from a destructor when another exception is called Stack unwinding. For example, if someone writes throw Foo (), the stack is expanded so that all the stack pages between throw Foo () and catch (foo e) {are ejected. This is called Stack unwrapping (Statck unwinding)

When the stack is expanded, all the local objects in the Stack page are destructor. If one of those destructors throws an exception (assuming it throws a bar object), the C + + runtime system is in an indecisive situation: should ignore bar and end in the catch (Foo e) {? You should ignore Foo and look for} catch (Bar e) {? There is no good answer--every choice will lose information.

So the C + + language guarantees that, when at this point, terminate () is invoked to kill the process. Sudden death.

An easy way to prevent this is to not throw an exception from the destructor. But if you're really smart, you can say "do not throw an exception from a destructor when dealing with another exception." But in the second case, you are in a difficult position: the destructor itself requires code handling to throw an exception, and some "other things" that the caller does not guarantee (possibly throwing an exception or doing "something else") when the destructor detects an error. So the complete solution is very difficult to write. So simply do some "other things". That is, do not throw exceptions from the destructor.

Of course, these words should not be "adduced" because there are always situations in which the rules are ineffective. But at least 99% of the case, this is a good rule.

If the constructor throws an exception, how do I handle the resource?

Each data member in the object should clean itself up.

If the constructor throws an exception, the destructor of the object will not run. If your object needs to undo some of the actions that have been done (such as allocating memory, opening a file, or locking a semaphore), the action that needs to be undone must be remembered by a data member within the object.

For example, you should assign the allocated memory to Fred, a "smart pointer" member object of an object, rather than allocating memory to an uninitialized fred* data member. This way, when the smart pointer dies, the destructor of the smart pointer deletes the Fred object. Standard Class auto_ptr is an example of this "smart pointer" class. You can also write your own reference counting smart pointers.

How do I change the string length of a character array to prevent memory leaks when someone throws an exception?

If you need to do a string, do not use a char array, because the array will cause trouble. You should replace them with objects that are similar to string classes.

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.