Search code examples
c++c++11exceptionnew-operator

Question about operator new overload and exception


Why this code snippet ouputs a lot of "here"?

I think the program should terminate when after throw std::invalid_argument( "fool" ); has been called.

#include <memory>
#include <iostream>

void* operator new(std::size_t size)
{
    std::cout << "here" << std::endl;
    throw std::invalid_argument( "fool" );   //commit out this, there would be many many ouputs
    return std::malloc(size);
}

void operator delete(void* ptr)
{
    return free(ptr);
}


int main()
{
    //std::unique_ptr<int> point2int(new int(999));

    int* rawpoint2int = new int(666);
}

Solution

  • The documentation for std::invalid_argument holds the clue:

    Because copying std::invalid_argument is not permitted to throw exceptions, this message is typically stored internally as a separately-allocated reference-counted string. This is also why there is no constructor taking std::string&&: it would have to copy the content anyway.

    You can see that the string argument is copied by design. This means that re-entering new is pretty much guaranteed if you are throwing this exception in this way.

    You should also be aware that malloc can return nullptr which will violate the design of operator new which should either return a valid pointer or throw.

    The normal kind of exception to throw in this case is std::bad_alloc. I cannot imagine why you are wanting to throw std::invalid_argument. I thought perhaps you were encountering this issue in a constructor somewhere and decided to test the allocation itself.

    Technically you can resolve the problem by passing a default-constructed string as the argument:

    // ... but, why would you do this?!! :(
    throw std::invalid_argument(std::string());  // will not allocate
    

    Eww, yucky. I recommend you find a more appropriate exception to throw (if you actually need one), or create your own non-allocating exception.