Item 49: new handler action

Source: Internet
Author: User

Item 49: new handler action

Item 49: Understand the behavior of the new-handler.

newWhen the memory application fails"bad alloc"Exception.std::set_new_handler()The specified error handling function ("new-handler ").

Set_new_handler ()

The new-handler function passes throughstd::set_new_handler()To set,std::set_new_handler()Defined in Medium:

namespace std{    typedef void (*new_handler)();    new_handler set_new_handler(new_handler p) throw();}

throw()Is an exception statement, indicating that no exception is thrown. For examplevoid func() throw(Exception1, Exception2)IndicatesfuncMay throwException1,Exception2Two exceptions.

set_new_handler()Is also very simple to use:

void outOfMem(){    std::cout<<"Unable to alloc memory";    std::abort();}int main(){    std::set_new_handler(outOfMem);    int *p = new int[100000000L];}

WhennewWhen the application does not have enough memory, it will continuously calloutOfMem. Therefore, a well-designed systemoutOfMemThe function should do one of the following:

  • Make more memory available;
  • Install a new "new-handler ";
  • Unmount the current "new-handler" and pass itnullToset_new_handlerYou can;
  • Throwbad_alloc(Or its subclass) is abnormal;
  • No, yesabortOrexit. Type-related error handling

    std::set_new_handlerSet globalbad_allocC ++ does not provide type-relatedbad_allocException Handling Mechanism. However, we can reloadoperator newWhen you create an object, temporarily set the global error handler function. Then, the global error handler function is restored.

    For exampleWidgetClass, you must first declare your ownset_new_handlerAndoperator new:

    Class Widget {public: static std: new_handler set_new_handler (std: new_handler p) throw (); static void * operator new (std: size_t size) throw (std :: bad_alloc); private: static std: new_handler current;}; // The static member must be defined outside the class. std: new_handler Widget: current = 0; std :: new_handler Widget: set_new_handler (std: new_handler p) throw () {std: new_handler old = current; current = p; return old ;}

    Aboutabort,exit,terminateDifferences:abortWill set the program to exit abnormally,exitWill set the program to exit normally, and C ++ will callterminate, It calls backstd::set_terminateThe set processing function, which is called by default.abort.

    Finallyoperator newThe function has three steps:

    1. Callstd::set_new_handlerWidget::currentSet as a global error handling function;
    2. Call globaloperator newTo allocate real memory;
    3. If memory allocation fails,Widget::currentAn exception is thrown;
    4. Whether it is successful or not, uninstall it.Widget::currentAnd install and callWidget::operator newThe previous global error handling function. Operator new

      We use RAII class to ensure that the original global error handling function can be restored, so that exceptions can continue to spread. For more information about RAII, see Item 13. First, write a RAII class that maintains the error handling function:

      Class NewHandlerHolder {public: explicit NewHandlerHolder (std: new_handler nh): handler (nh ){}~ NewHandlerHolder () {std: set_new_handler (handler);} private: std: new_handler handler; NewHandlerHolder (const HandlerHolder &); // disable the copy const NewHandlerHolder & operator = (const NewHandlerHolder &); // disable the value assignment operator };

      ThenWidget::operator newIs actually very simple:

      Void * Widget: operator new (std: size_t size) throw (std: bad_alloc) {NewHandlerHolder h (std: set_new_handler (current); return :: operator new (size); // call global new, throwing an exception or success} // function call ends, original error handler function recovers
      Use Widget: operator new

      Customer useWidgetThe method also conforms to the Convention of the basic data type:

      Void outOfMem (); Widget: set_new_handler (outOfMem); Widget * p1 = new Widget; // if it fails, outOfMemstring * ps = new string will be called; // if it fails, the Global new-handling function will be called. If there is no such function, the Widget: set_new_handler (0) will be absent ); // set the exception handling function of the Widget to empty Widget * p2 = new Widget; // If the Widget fails, an exception is thrown immediately.
      General base class

      After carefully observing the above Code, it is easy to find that the logic of the custom "new-handler" is actuallyWidgetIs irrelevant. We can extract these logics as a template base class:

      template
            
             class NewHandlerSupport{public:    static std::new_handler set_new_handler(std::new_handler p) throw();    static void * operator new(std::size_t size) throw(std::bad_alloc);private:    static std::new_handler current;};template
             
              std::new_handler NewHandlerSupport
              
               ::current = 0;template
               
                std::new_handler NewHandlerSupport
                
                 ::set_new_handler(std::new_handler p) throw(){ std::new_handler old = current; current = p; return old;}template
                 
                  void * NewHandlerSupport
                  
                   ::operator new(std::size_t size) throw(std::bad_alloc){ NewHandlerHolder h(std::set_new_handler(current)); return ::operator new(size);}
                  
                 
                
               
              
             
            

      With this template base classWidgetAdd "new-handler" to support only public inheritance:

      class Widget: public NewHandlerSupport
            
             { ... };
            

      ActuallyNewHandlerSupportImplementation and template parametersTIt is completely irrelevant. The template parameter is added becausehandlerIs a static member so that the compiler can generatehandlerInstance.

      Nothrow new

      Before December 31, 1993operator newWill return when the failurenullInstead of throwing an exception. Today's C ++ still supports such nothrowoperator new:

      Widget * p1 = new Widget; // The bad_alloc exception assert (p1! = 0); // This always sets up the Widget * p2 = new (std: nothrow) Widget; if (p2 = 0 )... // p2 = 0 upon failure

      "Nothrow new" only applies to memory allocation errors. The constructor can also throw an exception, which cannot be guaranteed to benewThe statement is "nothrow.

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.