What is the use of std::nothrow and std::new_handler in standard header file <new>

StackOverflow https://stackoverflow.com/questions/13506234

  •  01-12-2021
  •  | 
  •  

문제

I came across a small standard header file <new>. I have probably not seen its direct use before. Here is the g++ version for those who are interested.

Below part is of my interest:

  struct nothrow_t { };
  extern const nothrow_t nothrow;
  /** If you write your own error handler to be called by @c new, it must
   *  be of this type.  */
  typedef void (*new_handler)();
  /// Takes a replacement handler as the argument, returns the previous handler.
  new_handler set_new_handler(new_handler) throw();
  1. How struct nothrow_t and its object nothrow are used by programmers ? Is the object really needed to be extern?
  2. When does new_handler used ?
  3. Why all the operator new/delete are declared in extern C++ block ?
도움이 되었습니까?

해결책

nothrow_t is used to tell operator new to operate in the backwards-compatible "return null on failure rather than throwing an exception" mode.

That is, if you see code like this:

int * idx = new(std::nothrow) int;

that would be nothrow_t at work. For the relevant sections in the standard start at (as of C++11 N3376) 17.6.4.6 [replacement.functions]/1 and work your way down from there.

To answer your specific questions:

  1. Yes, it really does have to be extern, at least according to 18.6 [support.dynamic]/1, which includes:

    namespace std {
        class bad_alloc;
        class bad_array_new_length;
        struct nothrow_t {};
        extern const nothrow_t nothrow;
        typedef void (*new_handler)();
        new_handler get_new_handler() noexcept;
        new_handler set_new_handler(new_handler new_p) noexcept;
    }
    

    Moreover, 17.6.2.3 [using.linkage]/1 says "Entities in the C++ standard library have external linkage (3.5)". Functions and classes (e.g. get_new_handler and set_new_handler above) don't explicitly need to be annotated to have external linkage because they have external linkage by default.

  2. new_handler is used when the user overrides the default operator new in use by calling set_new_handler. It is just a function pointer type.

  3. Probably because the signatures for operator new are not reserved in C. extern "C++" tells the compiler that it is allowed to do name mangling and other C++ specific things to those functions. This way you can compile one translation unit as C, and one as C++, and link them together in the same binary without worrying that someone in C land defined a function conflicting with the compiler's operator new.

다른 팁

Well, this is really a "read the documentation, please" question. Any good introduction book on C++ should discuss nothrow. For example, Bjarne's "The C++ Programming Language" does, as I recall.

But anyway, you use nothrow to turn std::bad_alloc exceptions into nullpointer results, and you use a new handler to possibly retry a failed allocation.

As a practical matter, remember to put :: in front of new when you use the nothrow feature, and in general when using the global placement new, in order to avoid picking up placement new from classes. Except that placement new should in general be avoided (as the very low level language feature that it is), I would do this even when it does not technically make sense. Just as a good habit.


Example:

#include <iostream>     // std::wcout, std::endl
#include <stdlib.h>     // EXIT_FAILURE, EXIT_SUCCESS
#include <new>          // std::nothrow
using namespace std;

int main()
{
    int* const p = ::new( std::nothrow ) int[0x7fffffff/sizeof(int)];
    if( !p )
    {
        cout << "Allocation failed!" << endl;
        return EXIT_FAILURE;
    }
    cout << "Alles success!" << endl;
    delete[] p;
    return EXIT_SUCCESS;
}

Output on my system:

[D:\dev\test]
> a
Allocation failed!

[D:\dev\test]
> _

Note that the above assumes a 32 bit process :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top