Effective C + + (understand the behavior of new handler)

author:

  • luixiao1223
    title: understanding the behavior of new handler

tips

In STL heap, the allocator object owned by container is not managed by new and delete

What is new handler

Before new throws a field to reflect an unsatisfied memory requirement, it will call a user specified error handling function. This is new handler

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

You can use it like this

void outOfMem()
{
    std::cerr << "Unable to satisfy request for memory\n";
    std::abort();
}

int main()
{
    std::set_new_handler(outOfMem);
    int *pBigDataArray = new int[100000000L];
}

When new can't satisfy the memory request, it will call the new handler function constantly
A good new handler should have

  1. Make more memory available
  2. Installing another new handler should
  3. Write in new handler
  4. Throwing bad_alloc will be thrown out
  5. Do not return, call abort and exit directly

application

We want different classes to have different memory processing methods. We need class to define its own new
Then the standard operation is

  1. Set handler
  2. new operation
  3. Restore scene
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 currentHandler;
};

std::new_handler Widget::currentHandler = 0;

std::new_handler Widget::set_new_handler(std::new_handler p) throw()
{
    std::new_handler oldHandler = currentHandler;
    currentHandler = p;
    return oldHandler;
}

Handler Holder

class NewHandlerHolder {
public:
    explicit NewHandlerHolder(std::new_handler nh)
        : handler(nh) {}
    ~NewHandlerHolder()
    { std::set_new_handler(handler); }
private:
    std::new_handlerhandler;
    NewHandlerHolder(const NewHandlerHolder&);
    NewHandlerHolder&
    operator=(const NewHandlerHolder&);
};

Define your own new operator

void* Widget::operator new(std::size_t size) throw(std::bad_alloc)
{
    NewHandlerHolder
        h(std::set_new_handler(currentHandler));
    return ::operator new(size); //Call global new
    // Due to the use of new handlerholder, this sentence will be followed by the recovery of the scene
}

The method used is

void outOfMem();
Widget::set_new_handler(outOfMem);Widget *pw1 = new Widget;
std::string *ps = new std::string;
Widget::set_new_handler(0);
Widget *pw2 = new Widget;

A better version, using inheritance

template<typename T>
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 currentHandler;
};


template<typename T>
std::new_handler
NewHandlerSupport<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);
}

template<typename T>
std::new_handler NewHandlerSupport<T>::currentHandler = 0;

In this way, each different class has its own unique holder
We don'T use T, but T gives us a unique holder

class Widget: public NewHandlerSupport<Widget> {
}; //Widget inherits from a template whose type parameter is widget, that is, it itself

One More Thing

class Widget { ... };

Widget *pw1 = new Widget;

if (pw1 == 0)
    ...
Widget *pw2 = new (std::nothrow) Widget;

if (pw2 == 0)
    ...

In fact, it's impossible not to throw an exception. But you use std::nothrow only to ensure that the first layer of new does not throw an exception. If it fails, it will return null. However, there may be new operations in the constructor of Widget, and the exception throwing behavior will not be controlled by you

104 original articles published, praised 11, 10000 visitors+
Private letter follow

Posted by thatsgreat2345 on Wed, 12 Feb 2020 01:35:39 -0800