Search code examples
c++stdnothrow

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


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 ?

Solution

  • 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.