Valid tive C ++, 3rd edition, item 29: Strive for exception-safe code (abnormal Security Code) (on)

Source: Internet
Author: User

Item 29: Get exception-safe code (abnormal security code)

By Scott Meyers

Translator: fatalerror99 (itepub's nirvana)

Release: http://blog.csdn.net/fatalerror99/

Exception safety (abnormal security) is a bit like pregnancy (pregnant )...... However, keep this idea for a while. We cannot really talk about reproduction until we have exclusive to courtship ). (The three words used by the author in this section have dual meanings. Pregnancy can also be understood as rich and meaningful, reproduction can also be understood as reproduction and regeneration, and courtship can also be understood as struggle and seeking. In order to match the subsequent translations, follow the current translation method. -- Translator's note)

Suppose we have a class that represents a GUI menu with a background image. This class is designed for a threaded environment (multi-threaded environment), so it has a mutex for concurrency control (Concurrency Control ):

Class prettymenu {
Public:
...
Void changebackground (STD: istream & imgsrc); // Change Background
... // Image

PRIVATE:

Mutex; // mutex for this object

Image * bgimage; // current background image
Int imagechanges; // # Of times image has been changed
};

Consider the possible implementation of the changebackground function of the prettymenu:

Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock (& mutex); // acquire mutex (as in item 14)

Delete bgimage; // get rid of old background
++ Imagechanges; // update image change count
Bgimage = new image (imgsrc); // install new background

Unlock (& mutex); // release mutex
}

From the exception safety (abnormal security) point of view, this function is terrible. Exception safety has two requirements, but none of them are met here.

When an exception (exception) is thrown, exception-safe functions should be:

  • Leak no resources(No resource leakage ). The above Code did not pass this test, because if the "new image (imgsrc)" expression triggers an exception, the unlock call will never be executed, the mutex will also be suspended forever.
  • Don't allow data structures to become into upted(The data structure cannot be damaged ). If "new image (imgsrc)" throws (throws an exception), bgimage is left to point to a deleted object. In addition, imagechanges has been added even though a new image has not been set in place. (On the other hand, the old image is clearly deleted, so I expect you to argue that the image has been "changed .)

It is easier to avoid resource leak (resource leakage) Because item 13 explains how to use objects to manage resources, item 14 introduces the lock class as a method to ensure that the mutex is released in a timely and appropriate manner:

Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock ml (& mutex); // From Item 14: acquire mutex and
// Ensure its later release
Delete bgimage;
++ Imagechanges;
Bgimage = new image (imgsrc );
}

One of the best things about resource management classes like lock is that they usually shorten functions. See how to make the unlock call no longer needed? As a general rule, less code is better code, because it can be less misled and less misunderstood during changes.

As resource leak (resource leakage) is left behind, we can focus our attention on the data structure partition uption (Data Structure damaged) problem. Here we have a choice, but before we can choose, we must first define our selection terms.

Exception-safe functions provides one of the following three guarantees:

  • Function provisionThe basic guarantee(Basic guarantee), promise that if an exception is thrown, everything left in the program is legal. No objects or data structure is damaged, and all objects are in an internal harmonic state (all class invariants (class constants) are satisfied ). However, the precise state of the program may be unpredictable. For example, we can rewrite changebackground so that when an exception is thrown, The prettymenu object can retain the original background image, or it can hold some Default background images, however, the customer cannot predict which one it is. (To find out this, they probably have to call a member function that tells them what the current background image looks like .)
  • Function provisionThe strong guarantee(Strong guarantee), promise that if an exception is thrown, the state of the program will not change. Calling such a function is likeAtomic(Atomic), if they succeed, they are completely successful. If they fail, the state of the program is the same as they have never been called.

Working with functions that provide strong guarantee (strong guarantee) is easier than working with functions that only provide basic guarantee (basic guarantee), because calls provide strong guarantee (strong guarantee) there are only two possible Program states after the function: the function is successfully executed as expected, or the current state is maintained when the function is called. In comparison, if an exception is thrown by calling a function that only provides basic guarantee (basic guarantee), the program may exist in any legal state.

  • Function provisionThe nothrow guarantee(Do not throw a guarantee), promise not to throw an exception, because they only do what they can ensure. All the operations on built-in types (built-in types) (such as ints, pointers, and so on) are nothrow (not throw) (that is, provide nothrow guarantee (no throw guarantee )). This is an essential basic component of exception-safe code.

Assuming that a function with the empty exception specification (null exception Specification) does not throw, it seems reasonable, but this is not necessarily true. For example, consider this function:

Int dosomething ()Throw (); // Note empty exception spec.

This does not mean that dosomething will never throw an exception, but that if dosomething throws an exception, it is a serious error and should call unexpected function [1]. In fact, dosomething may not provide any exception guarantee at all. The declaration of a function (if any, including its exception specification (exception Specification) cannot tell you whether a function is correct, portable, or efficient, even if it does, it cannot tell you which exception safety guarantee it provides (exception security guarantee ). All these features are determined by the implementation of the function, rather than its declaration.

[1] about unexpected function, you can turn to your favorite search engine or all-encompassing C ++ textbooks. (You may be lucky to find set_unexpected, which is used to specify the unexpected function .)

Exception-safe code must provide one of the above three guarantees. If it is not provided, it is not exception-safe. Therefore, the choice is to decide which guarantee each function you write must provide. Unless you want to handle the legacy code of exception-unsafe (abnormal and insecure) (This item will be discussed later ), only when your most sophisticated demand analysis team identifies a need for your applications to leak resources and run on damaged data structures, exception Safety Guarantee (exception security guarantee) is not provided to become an option.

As a general rule, you should provide the most powerful guarantee that can be achieved. From the exception safety (abnormal security) point of view, nothrow functions (a function that does not throw) is awesome, however, it is hard to call functions that may throw exceptions without calling C ++. Anything that uses dynamic memory allocation (for example, all STL containers). If you cannot find enough memory to satisfy a request (see item 49), in typical cases, it will throw a bad_alloc exception. The nothrow guarantee is provided as long as you can, but for most functions, the choice is between the basic guarantee and the strong guarantee.

In the case of changebackgroundAlmost(Almost) strong guarantee (strong assurance) is not difficult. First, we change the bgimage data member type of the prettymenu from a built-in image * pointer (pointer) to the SMART Resource-management pointers (SMART Resource Management pointer) described in item 13). Frankly speaking, it is a good idea to prevent resource leaks. The fact that it helps us provide strong exception Safety Guarantee (strong exception security guarantee) further reinforces Item 13's arguments-using objects (such as smart pointers (smart pointers )) resource management is the foundation of good design. In the following code, I show the use of tr1: shared_ptr, because it is more intuitive when performing a normal copy, which makes it more desirable than auto_ptr.

Second, we rearrange the statements in changebackground so that imagechanges is not added until the image changes. As a general rule, this is a good strategy-until something actually happens, and then changes the state of an object to indicate that something has happened.

This is the modified Code:

Class prettymenu {
...
STD: tr1: shared_ptr <image>Bgimage;
...
};

Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock ml (& mutex );

Bgimage. Reset (new image (imgsrc )); // Replace bgimage's internal
// Pointer with the result of
// "New Image" expression
++ Imagechanges;
}

Note that you no longer need to manually delete old images because these images are processed internally by smart pointer. In addition, a new image is deleted only when it is successfully created. More accurately, this function is called only when the tr1: shared_ptr: reset function parameter ("new image (imgsrc)" result) is successfully created. Delete is used only when a reset is called. Therefore, if this function is never used, delete is never used. At the same time, please note that the use of an object (tr1: shared_ptr) that manages resources (dynamically allocated images) shortens the length of changebackground.

As I said, these two changesAlmost(Almost) ability to make changebackground provide strong exception Safety Guarantee (strong exception security guarantee ). What are the shortcomings in the United States? The imgsrc parameter. If image Constructor (constructor) throws an exception, the read Mark of input stream (input stream) may have been moved, this movement becomes a visible state change for other parts of the program. Until changebackground solves this problem, it can only provide basic exception Safety Guarantee (Basic exception security guarantee ).

(This Article is not complete. Click here to answer the next article)

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.