Objective C ++ cla29: it is worthwhile to work hard for "exceptional security"

Source: Internet
Author: User

A class is used to display a GUI menu with a background pattern. This class is used in a multi-threaded environment:

Class prettymenu {
Public:
...
Void changebackground (STD: istream & imgsrc );
...
PRIVATE:
Mutex;
Image * bgimage;
Int imagechanges;
};
Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock (& mutex );
Delete bgimage;
++ Imagechanges;
Bgimage = new image (imgsrc );
Unlock (& mutex );
}

From the perspective of exception security, this function is very bad. "Exception Security" has two conditions: When an exception is thrown, functions with exception security will:

No resources are disclosed. The above Code did not do this, because once "new image (imgsrc)" causes an exception, the unlock will not be executed, so the mutex will always be held.

Data corruption is not allowed. If "new image (imgsrc)" throws an exception, bgimage points to a deleted object, and imagechanges has been accumulated. In fact, no new image has been installed successfully.

It is easy to solve the problem of resource leakage,

Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock ml (& mutex); // comes from Clause 14;
Delete bgimage;
++ Imagechanges;
Bgimage = new image (imgsrc );
}

The best thing about "Resource Management" such as lock is that they usually make functions shorter. Less code is better code, because there are fewer opportunities for errors.

The exception-safe function provides one of the following three guarantees:

Basic commitment: if an exception is thrown, everything in the program remains in the valid state. No object or data structure is corrupted, and all objects are in an internal consistent State (for example, all class constraints continue to be met ). However, the actual state of the program may be unpredictable. In the above example, changebackground allows the prettymenu object to continue to possess the original background image or a default background image once an exception is thrown, but the customer cannot predict the situation. If you want to know, they may have to call a member function to find out what the background image looks like at the time.

It is strongly guaranteed that the program State will not change if an exception is thrown. If the function is successful, it is completely successful. Otherwise, the program will return to the status before the function is called.

Do not throw (nothrow) guarantee: Promise never throw an exception because they can always complete the functions they previously promised. All operations acting on built-in types (such as ints and pointers) provide the nothrow guarantee. The function with "Blank exception details" must be a nothrow function, but it is not all right

Int dosomething () Throw (); // "Blank exception details"

This does not mean that dosomething will never throw an exception, but that if an exception is thrown, it will be a serious error and unexpected function calls will occur. In fact, dosomething may not provide any exception guarantee at all. The declarative function (including exception details) does not tell you whether it is correct, portable, or efficient, nor does it provide any exception security guarantee.

Exception-safe code must provide one of the preceding three guarantees. Otherwise, it does not have exceptional security.

In general, the strongest guarantee that can be implemented should be provided. The nothrow function is great, but it is difficult to call any function that may throw an exception in the C part of C ++ field. Therefore, for most functions, the choice usually falls between the basic guarantee and the strong guarantee.

For changebackground, first, change from a built-in pointer of the image type to a smart pointer for "Resource Management". Second, rearrange the order of statements in changebackground, after the image is changed, add imagechanges.

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

Void prettymenu: changebackground (STD: istream & imgsrc)
{
Lock ml (& mutex );
Bgimage. Reset (new image (imgsrc ));
++ Imagechanges;
}

You do not need to manually delete the old image. It is called only after the reset parameter (that is, the execution result of "New image (imgsrc)") is successfully generated. The imgsrc parameter is insufficient in the US. If the image constructor throws an exception, it is possible that the read Mark (read marker) of the input stream has been removed, and such a move is a visible state change for the rest of the program. Therefore, we only provide basic exception security assurance before solving this problem.

There is a general policy that is typically guaranteed to be "copy and swap": Make a copy of the object to be modified,

Make all necessary modifications on that copy. If any modification action throws an exception, the source object remains unchanged. After all the changes are successful, replace the modified copy and original object in a swap that does not throw an exception.

The implementation is usually to put all "data of subordinate objects" from the original object into another object, and then assign a pointer to the source object, pointing to the so-called implementation object (Implementation object, that is, a copy ). For prettymenu, the typical syntax is as follows:

Struct pmimpl {
STD: tr1: shared_ptr <image> bgimage;
Int imagechanges;
};
Class prettymenu {
...
PRIVATE:
Mutex;
STD: tr1: shared_ptr <pmimpl> pimpl;
};
Void prettymenu: changebackground (STD: istream & imgsrc)
{
Using STD: swap;
Lock ml (& mutex );
STD: tr1: shared_ptr <pmimpl> pnew (New pmimpl (* pimpl ));
Pnew-> bgimage. Reset (new image (imgsrc); // modify the copy
++ Pnew-> imagechanges;
Swap (pimpl, pnew); // replace Data
}

Although the copy and SWAP policy makes a good way to change "All or all", it generally does not guarantee the strong exceptional security of the entire function.

Such as somefunc. The copy-and-swap policy is used, but the function also includes calls to other functions F1 and F2:

Void somefunc ()

{

...

F1 ();

F2 ();

...

}

Obviously, if the exception security of F1 or F2 is lower than "strongly guaranteed", it is difficult to make somefunc "strongly abnormal security ". If both F1 and F2 are "strongly abnormal and secure", the situation will not improve. After all, if F1 ends successfully, the program State may change in any aspect. Therefore, if F2 then throws an exception, the program state is different from that before somefunc is called, this is even true when F2 does not change anything.

The problem occurs when "joint impact". If a function operates only partial states, it is relatively easy to provide strong assurance. However, when a function has a joint impact on "non-local data, it is much more difficult to provide strong guarantees. For example, if the impact of calling F1 is that a database has been modified, it is difficult to make somefunc highly secure. Another topic is efficiency. Copy-and-swap is easy to use. You may be unable to (or unwilling to) supply time and space. Therefore, "strong assurance" is not practical at any time.

When "strong assurance" is impractical, you must provide "basic assurance ".

You should select the strongest level under "realistic and operable" conditions. Only when your function calls traditional code can you set it to "without any guarantee ".

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.