Ответ 1
Стандартная [ [basic.start.main]] задает следующие ограничения для функции main
:
Реализация должна допускать:
- функция(), возвращающая int и
- функция (int, указатель на указатель на char), возвращающая int
При этом:
Программа, определяющая main как удалённую или объявляющую main, является встроенной, статической или constexpr, плохо сформирована.
На практике спецификация noexcept
для main
отсутствует. С другой стороны, noexcept
разрешен как спецификатор для любой функции. Это означало бы, что main noexcept
не плохо сформировался.
Какая разница w/o noexcept
main?
Поскольку стандарт не очень явственен о noexcept
для функции main
, как мы видели, мы можем попытаться вычесть некоторое поведение и проверить реализации.
Из здесь:
Всякий раз, когда генерируется исключение, и поиск обработчика встречается с самым внешним блоком не-бросающей функции, вызывается функция std:: terminate.
В то время как общее правило для исключений, из здесь:
Если исключение выбрано и не поймано, включая исключения, которые исключают начальную функцию std:: thread, главную функцию и конструктор или деструктор любых статических или поточно-локальных объектов, тогда вызывается std:: terminate, Реализовано определение того, происходит ли разворачивание стека для неперехваченных исключений.
Это означает, что функция throw
из main
всегда генерирует вызов std::terminate
. Независимо от noexcept
спецификации main
.
Сторона реализации:
Действительно, следующие коды:
int main(int argc, char* argvp[]) {
throw 1;
return 0;
}
и
int main(int argc, char* argvp[]) noexcept {
throw 1;
return 0;
}
будет производить тот же выходной сбор. Например, в 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
Это означает, что он будет разрешен в вызове std::terminate
, потому что кадр стека пуст на "основном уровне" независимо от спецификации noexcept
.