How are standard library exception bad_alloc thrown and std::abort called when there is no standard header included?

Viewed 57

I noticed that if new fails to find free-store memory to allocate, it will throw the standard library exception bad_alloc.

And in my understanding, if we don't catch an exception, std::abort will be called to terminate the program.

So I tried the following code (without #include anything):

int main()
{
    int* p = new int[99999999999999];  // or any number that is sufficiently large
}

and the result stated that abort() has been called.

I know that new is implicitly declared in each translation unit even if the header is not included.

However, in my understanding, if we don't #include any standard header, facilities like standard library exception and std::abort are not defined.

So, my question is, how are bad_alloc thrown and std::abort called in the about situation where they are not defined?

1 Answers

I know that new is implicitly declared in each translation unit even if the header is not included.

new is a keyword in C++ and new int[99999999999999] is a specific type of an expression, a new-expression. This is intrinsically part of the core language. There is no sense in which this new could be declared. It is just a keyword part of a specific syntax construct. It is not a function call or anything like that.

<new> declares overloads of operator new, which is a function that can be declared. operator new is however not the same as a new-expression. They both use the keyword new and the new-expression typically calls a operator new overload, but they are completely different things.


Whether or not std::bad_alloc has been declared in your translation unit is irrelevant to whether or not the new-expression can throw it. The new-expression is part of the core language and the standard library is also intrinsic part of the language itself, they cannot be strictly separated. It would be completely fine to specify the language in such a way that std::bad_alloc is thrown even if no standard library header is included. There doesn't literally have to be some C++ code included from a standard library header containing a throw expression. The compiler can just insert it as required.

However, std::bad_alloc here isn't thrown from the new-expression itself. It is thrown from the operator new which is implicitly declared and called by the new-expression. If this is implemented in normal C++ code, then the exception type needs only be declared where the actual throw expression is placed inside operator new's definition, not where the exception is propagated. The definition of the operator new will be typically located in some dynamic library supplied with the standard library implementation.

A better example would be std::bad_array_new_length which would be thrown for example by an array-new-expression if the number of elements requested is not a compile-time constant and happens to be negative before conversion to std::size_t at runtime. This exception is thrown directly from the new-expression, not the operator new, even if no standard library header is included.


And similarly, because std::abort (and std::terminate) are also part of the standard library and so intrinsically part of the language, they can still be called e.g. when an exception is not caught, even if none of the user code includes a standard library header and so no declaration for either function is available in the user translation units.

Related