Exercise tive C ++ item49: Understanding new handler's behavior

Source: Internet
Author: User

1. new_handler function: the function called when operator new or operator new [] memory allocation fails.

Set_new_handler function: This function is used to allocate more memory. If it succeeds, it will return. Otherwise, it will throw a bad_alloc exception (or its derived class Object) or call the abort () or exit () of cstdlib () the function is forced to exit.

References: http://www.cplusplus.com/reference/std/new/set_new_handler/

Http://www.cplusplus.com/reference/std/new/new_handler/

2. when operator new fails to allocate memory (insufficient), it first calls the New-handler function specified by the customer and throws an exception (the old behavior is to return a null pointer ). The customer uses set_new_handler to set this behavior. It is a standard library function declared in <New>:

Namespace STD {typedef void (* new_handler) (); // pointer to the Function
New_handler set_new_handler (new_handler p) Throw (); // gets the function pointer that should be called when the memory allocation fails, and returns the function that is being executed before the call (but will be replaced immediately) new-handler function pointer
} When operator new cannot meet the memory application, it will call the new-handler function until the memory is sufficient.

Note: Operator new functions are different from new functions. The former is the implementation in the standard library. It is a function, but not a overload, while the latter is an expression.

3. A well-designed new-handler function must do the following:

  • So that more memory can be used. One way is that the program allocates a large amount of memory at the beginning. When new-handler is called, the memory space is returned to the program.
  • Install another new-handler. If the current new-handler function cannot apply for sufficient memory, you can use set_new_handler to replace it with another suitable version.
  • Remove the New-handler and pass the NULL pointer to set_new_handler. Once no new-handler is installed, operator new will throw an exception when the allocation fails.
  • Throw an exception of bad_alloc (or its derived class object. Such exceptions will not be caught by operator new, so they will be propagated to the memory application.
  • If no value is returned, abort () or exit () is usually called ().

4. to support the class-specific new-handler, you can declare the required new_handler function in the class and provide the class-specific set_new_handler (specify new-handler) and operator new (ensure that the global new-handler is replaced with the class-exclusive New-handler in the process of allocating Class Object Memory. The specific process is as follows:

(1) declare a static member function of the new_handler type to point to the new-handler of the class. For example:

   1:  class Widget{
   2:   
   3:  public:
   4:   
   5:  static std::new_handler set_new_handler(std::new_handler p) throw();
   6:   
   7:  static void* operator new(std::size_t size) throw(std::bad_alloc);
   8:   
   9:  private:
  10:   
  11:  static std::new_handler currentHandler;
  12:   
  13:  };

Note that the static member must be defined outside the class (unless it is const and INT type), so you need to write it like this:

std::new_handler Widget::currentHandler = 0;
(2) The set_new_handler function stores the obtained pointer and returns the pointer stored before the call (same as the standard set_new_handler:
std::new_handler Widget::set_new_handler(std::new_handler p) thorw(){std::new_handler oldHandler = currentHandler;currentHandler = preturn oldHandler;}
(3) Enable operator new of this class to do the following:
  • Call the standard set_new_handler to inform the error handler of this class. This will install the new-handler of this class as the Global New-handler.
  • Call the global operator new to execute the actual memory allocation. If the allocation fails, the global operator new will call the new-handler of the class, because the function has just been installed as a global new-handler. If the global new-handler cannot allocate enough memory, the bad_alloc exception will be thrown. In this case, operator new of this class must restore the original Global New-handler and then spread the exception. To ensure that the original New-handler can always be reinstalled, this class regards the global new-handler as a "resource" and uses the resource management object to prevent resource leakage.
  • If the global operator new can allocate enough memory, a pointer is returned pointing to the allocated address. The destructor of this class manages global new-handler, and it automatically restores the Global New-handler before the class operator new is called.
5. instance: Starting from the resource processing class, there are only basic raiI operations. A resource is obtained during the construction process and returned during the analysis process:
Class newhandlerholder {public: explicit newhandlerholder (STD: new_handler NH): handler (NH) {}// get the current new-handler ~ Newhandlerholder () {STD: set_new_handler (handler);} // release new-handlerprivate: STD: new_handler handler; // save New-handlernewhanlderholder (const newhandlerholder &); // block replication behavior newhandlerholder & operator = (const newhandlerholder &);};
Suppose there is a class widget that implements the operator new method:
Void * Widget: Operator new (STD: size_t size) Throw (STD: bad_alloc) {newhandlerholder H (STD: set_newhandler (currenthandler )); // install the new-handlerreturn: Operator new (size) of the widget; // allocate memory or throw an exception to restore global new-handler}
The customer of the widget should adopt the following method: New-handler:
Void outofmem (); // declare the processing function widget when memory allocation fails: set_new_handler (outofmem ); // set the above function to the new-handler function widget * pw1 = new widget of the widget; // if the memory allocation fails, call outofmem () STD :: string * PS = new STD: string; // If memory allocation fails, call the Global New-handler function (if any) Widget: set_new_handler (0 ); // set the new-handler of the widget to be empty and the widget * pw2 = new widget of the exclusive version is lost. // if the memory allocation fails, an exception is thrown.

The preceding method can be abstracted to create a base class of the Mixin style, which allows the derived class to inherit a single specific capability (here "set the class exclusive New-Handler"), abstract The base class as a template class to improve reusability.

Template <typename T> // a base class in the Mixin style to support the exclusive set_new_handlerclass 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 );... // other operator new versions: Private: static STD: new_handler currenthandler;}; Template <typename T> STD: new_handlernewhandlersupport <t >:: set_new_handler (STD: new_handler P) throw () {STD: new_handler oldhandler = currenthandler; currenthandler = P; return oldhandler;} template <typename T> void * newhandlersupport <t >:: operator new (STD :: size_t size) Throw (STD: bad_alloc) {newhandlerholder H (STD: set_new_handler (currenthandler); Return: Operator new (size );} // initialize each currenthandler as nulltemplate <typename T> STD: new_handler newhandlersupport <t >:: currenthandler = 0;
For a specific class, it is easy to add the exclusive set_new_handler: inheritance.
Class Widget: Public newhandlersupport <widget> {... // same as the previous one, but it does not need to declare set_new_handler or operator new };
6. The old operator new returns NULL after memory allocation fails. to be compatible with the old Code, C ++ provides
Operator new in the first form, called the nothrow form, uses the nothrow object (defined in the header <New>
File ). We recommend that you do not use it.

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.