Is the following code valid in C++?
int main() noexcept { }
Both clang++ 3.8.0 and g++ 7.2.0 compile it fine (with -std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors
compilation flags).
Is it allowed to use complex conditions (e.g. including noexcept
operator) in the noexcept
specification of the main
function?
And what about C++17? As I know noexcept
specifier becomes the part of the function type in this revision of the standard.
"Function can be declared 'noexcept'." If code is not supposed to cause any exceptions, it should be marked as such by using the 'noexcept' specifier. This would help to simplify error handling on the client code side, as well as enable compiler to do additional optimizations.
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.
In contrast, noexcept(false) means that the function may throw an exception. The noexcept specification is part of the function type but can not be used for function overloading. There are two good reasons for the use of noexcept: First, an exception specifier documents the behaviour of the function.
Explicit instantiations may use the noexcept specifier, but it is not required. If used, the exception specification must be the same as for all other declarations.
The standard [[basic.start.main]] specifies the following constraints on the main
function:
An implementation shall allow both:
— a function of () returning int and
— a function of (int, pointer to pointer to char) returning int
Moreover:
A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-formed.
In practice, there is no specification about noexcept
qualifier for main
. On the other hands, noexcept
is allowed as a specifier for whatever function. That would imply main noexcept
is not ill-formed.
noexcept
main?Since the standard is not very explicit about noexcept
for main
function as we've seen, we can try to deduct some behaviour and check the implementations.
From here:
Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called.
While the general rule for exceptions, from here:
If an exception is thrown and not caught, including exceptions that escape the initial function of std::thread, the main function, and the constructor or destructor of any static or thread-local objects, then std::terminate is called. It is implementation-defined whether any stack unwinding takes place for uncaught exceptions.
This implies that throw
from main
function always generates a std::terminate
invocation. Regardless of noexcept
specification of the main
.
Indeed, the following codes:
int main(int argc, char* argvp[]) { throw 1; return 0; }
and
int main(int argc, char* argvp[]) noexcept { throw 1; return 0; }
will produce the same output assembly. For example in GCC:
main: movl $4, %edi subq $8, %rsp call __cxa_allocate_exception xorl %edx, %edx movl $1, (%rax) movl typeinfo for int, %esi movq %rax, %rdi call __cxa_throw
That means it will be resolved into an invocation of std::terminate
because the stack frame is empty at "main level" regardless of noexcept
specification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With