C + + Scopeexitguard

Source: Internet
Author: User

When it comes to native languages, we have to say resource management, because resource management has always been a big problem in native languages, in which memory management is a big problem in resources, because heap memory needs to be allocated and released manually, so you must ensure that memory is released. The general principle for this is "who assigns who is responsible for release", but even so still often leads to memory leaks, wild pointers, and so on. Not to mention this manual release to the API design problems (such as Win32 API WideCharToMultiByte is a typical example, you need to provide a buffer to receive the results of the encoding conversion, but you can not ensure that your buffer is large enough, So there is a two call pattern, the first time to give a null buffer, so the API returns the size of the desired buffer, according to the size of the allocation buffer after the second call it, not to mention more awkward.

The managed language introduced a GC to solve the problem, with the idea that "memory management is too important to be given to programmers." But GC also often has its own problems with native development. On the other hand, native also often criticized the GC, saying that "memory management is too important to be given to the machine to do."

C + + may be the first language to offer a perfect compromise (though this mechanism is not really easy to use until the advent of c++11), i.e. it is not entirely given to the machine, and not entirely to the programmer, but the programmer first specifies what to do in the code, and when to do so, How to ensure that it will be executed is determined by the compiler .

The first is that C++98 provides the language mechanism: The destructor is automatically called when the object is out of scope. Next, Bjarne Stroustrup defined the RAII (Resource acquisition is initialization) paradigm in TC++PL (that is, the resources needed to construct the image should be initialized in the constructor, These resources are freed when the object is refactored ). Raii means that we should use classes to encapsulate and manage resources, and for memory management, boost is the first smart pointer for industrial strength, and now smart pointers (shared_ptr and unique_ptr) are already part of c++11, and simply having smart pointers means that your C There should be almost no delete in the + + code base.

However, although the RAII paradigm is very good, but not enough to use, many times we do not want to a closehandle, ReleaseDC, GlobalUnlock and so on and go to the big fanfare to write another class out, So at these times we tend to manually adjust these release functions for fear of trouble, and one disadvantage of manual tuning is that if an exception occurs between the resource request and the release, the release will not occur, and the manual release needs to be released at all exits of the function. If someone changes the code one day, adds a return, and forgets to release the function before return, the resource leaks. Ideally, we want the language to support this paradigm:

void foo () {    HANDLE h = CreateFile (...);    On_scope_exit {CloseHandle (h);}    ...//Use the file}

The code inside the On_scope_exit is the same as in the destructor: No matter how the current scope exits, it is bound to be executed.

In fact, as early as 2000, Andrei Alexandrescu published an article in DDJ magazine that proposed the facility called Scopeguard, but at the time, C + + did not have a very good language mechanism to support the facility, So Andrei used you can think of all kinds of artifice just made a out, and then boost also joined the Scopeexit library, but these are built in c++98 incomplete language mechanism, so its implementation is very unnecessary cumbersome and imperfect, I was dancing in fetters (which is one of the main reasons why C++98 's General library was criticized), and then Andrei the facility into the D language as part of the D language feature (one of the most amazing parts).

Then came the release of C++11, after the release of C++11, many people began to re-realize this is extremely important for the security of the facilities, but the majority of the implementation of the 2000-year Andrei of the original article, more or less the complexity, but in fact, the C + + With 11 of lambda function and tr1::function combined, this facility can be simplified to the point where the brain is crippled:

Class Scopeguard{public:    explicit Scopeguard (Std::function<void () > Onexitscope)         : Onexitscope_ ( Onexitscope), Dismissed_ (False)    {}    ~scopeguard ()    {        if (!dismissed_)        {            onexitscope_ ()        }    }    void Dismiss ()    {        dismissed_ = true;    } Private:    std::function<void () > onexitscope_;    BOOL Dismissed_;private://noncopyable    Scopeguard (Scopeguard const&);    scopeguard& operator= (Scopeguard const&);

The use of this class is simple, you give it a std::function, it is responsible for the execution of the destruction, most of the time this function is a lambda, for example:

HANDLE h = CreateFile (...); Scopeguard OnExit ([&] {CloseHandle (h);});

OnExit faithfully executes CloseHandle at the time of the destruction. In order to avoid the trouble of naming this object (if there are multiple variables, the name is cumbersome), you can define a macro that mixes the line number into the variable names so that each defined Scopeguard object is uniquely named.

#define SCOPEGUARD_LINENAME_CAT (name, line) name# #line # define SCOPEGUARD_LINENAME (name, line) scopeguard_linename_ CAT (name, line) #define ON_SCOPE_EXIT (callback) Scopeguard Scopeguard_linename (EXIT, __line__) (callback)

The Dismiss () function is also part of the original design of Andrei, which is designed to support rollback mode, such as:

Scopeguard Onfailurerollback ([&] {/* rollback */}); ...//do something that could failonfailurerollback.dismiss ();

In the above code, the rollback logic will be executed whenever an exception is thrown anywhere in the "do something" process. If "Do something" succeeds, Onfailurerollback.dismiss () is called, setting Dismissed_ to TRUE to block the execution of rollback logic.

ScopeguARD is an indispensable facility for automatic resource release and rollback in the case of code errors, c++98 because of the lack of lambda and tr1::function support, Scopeguard is not only complex, And it's very troublesome, there are many traps, and the c++11 immediately becomes extremely simple, which really becomes the facility to be used every day. The RAII paradigm of C + + is considered to be the best paradigm for the release of resource certainty (the Using keyword of C # will be indented in the case of a nested resource request release, rather than scale), and with On_scope_exit, it is very convenient to apply for releasing resources in C + +.

Acquire Resource1on_scope_exit ([&] {/* release Resource1 */}) acquire Resource2on_scope_exit ([&] {/* release R ESOURCE2 */}) ...

The benefit of doing this is not only that the code does not appear needlessly indented, but that the resource request and the freed code are visually adjacent to each other and never forgotten. Not to mention that you just need to write the freed code in one place, and whatever happens, the scope exits and we don't have to worry about the resources being freed. I believe this paradigm will soon become the standard way for all C + + code to allocate and release resources, because this is one of the really good parts of the evolution of C + + over the decades.

C + + Scopeexitguard

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.