3

This is pseudocode for the operator new:

while (true)
{
    Attempt to allocate size bytes
    if (the allocation was successful) 
        return (a pointer to the memory);

    // The allocation was unsuccessful; find out what the
    // current new-handling function is 
    new_handler globalHandler = set_new_handler(0);
    set_new_handler(globalHandler);
    if (globalHandler)
        (*globalHandler)();
    else
        throw std::bad_alloc();
  }

Questions :

1) Why first time 0 is passed as parametr to set_new_handler function?

2) It says that when allocation failed, new_handler function invoked, try to allocate momory and if and only if cant makes more memory, it return pointer to the start of allocated memory or if it cant, it throws bad_alloc exeption or returns null pointer and else body works, which throws a bad_alloc exeption. My question is why new_handler function sometimes throws exeption, if it can return null pointer and else body would do this ?

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
Seno Alvrtsyan
  • 241
  • 1
  • 11

2 Answers2

6

1) Why first time 0 is passed as parametr to set_new_handler function?

According to docs this code:

new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);

will

(1) set up handler to null pointer (passed as a parameter)

(2) retrieve function pointer to current handler into globalHandler variable

(3) set up handler back to what it was (whatever globalHandler is pointing to now)

This is performed to retrieve a function pointer to the current handler.

when allocation failed, new_handler function invoked, try to allocate momory

Unknown. I don't see where it allocates any memory here, as there is no code for it. User is free to do anything inside the new handler, but allocating memory is the last thing I would do. In fact, appropriate behavior would be to release some memory.

and if and only if cant makes more memory, it return pointer to the start of allocated memory or if it cant, it throws bad_alloc exeption or returns null pointer

Wrong. new_handler does not return anything, it's a typedef to a function pointer accepting no parameters and returning void:

typedef void (*new_handler)();

and else body works, which throws a bad_alloc exeption

else block only works when there is no handler installed (it is null pointer), not when new_handler "fails" or throws an exception or whatever

Read it like this:

void* operator new (std::size_t size, optional blah blah here) blah blah here
{
        while(true) // until universe exists (or a nearest power station)
        {

            // Try to allocate somehow

            // Allocation failed

            // Retrieved `global_handler` - a pointer to `void (*new_handler)` somehow


            if (globalHandler) // global_handler is not null pointer?
            {
                (*globalHandler)(); // no, invoke it and loop again
            }
            else
            {
                throw std::bad_alloc(); // it's null, nothing to do, exception, sorry
            }
    }
}

See also: How should I write ISO C++ Standard conformant custom new and delete operators?

Community
  • 1
  • 1
Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
4
  1. This is pre-C++11 code, where the only way to get the current new handler is via the slightly hackish approach of calling set_new_handler to set a new one, which also happens to return the previous handler. Now we have get_new_handler so that we can avoid the set-the-handler-to-null-pointer-to-obtain-the-original-and-then-restore-the-value circumlocution.

    In other words,

    new_handler globalHandler = set_new_handler(0);
    set_new_handler(globalHandler);
    

    is a more convoluted (and more dangerous) way of writing

    new_handler globalHandler = get_new_handler();
    

    in C++11.

  2. A new handler's return type is void - it doesn't return a pointer. Actually returning from a new handler (instead of throwing an exception or just terminating the program) essentially means "try again".

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • I mean that set_new_handler returns new_handler function pointer , which is null. – Seno Alvrtsyan Mar 03 '15 at 05:28
  • Interestingly, [cppreference](http://en.cppreference.com/w/cpp/memory/new/set_new_handler) still mentions the return value thing even though [`std::new_handler`](http://en.cppreference.com/w/cpp/memory/new/new_handler) is documented as `void (*)()`. Is this an error that should be fixed? – 5gon12eder Mar 03 '15 at 05:37
  • @5gon12eder What return value? `set_new_handler` does return something. I don't see that page mentioning the new handler itself returning a value. – T.C. Mar 03 '15 at 05:38
  • Sorry, my bad. I didn't read careful enough. `std::get_new_handler() != std::get_new_handler()()`. – 5gon12eder Mar 03 '15 at 05:39
  • @SenoAlvrtsyan So you mean why would a new handler throw something instead of calling `set_new_handler(nullptr);` to cause `bad_alloc` to be thrown? What if it can throw something more descriptive? – T.C. Mar 03 '15 at 05:39