Стандарт [[basic.start.main]] определяет следующие ограничения для функции main
:
Реализация должна позволять:
— функция(), возвращающая int и
— функция (int, указатель на указатель на char), возвращающая int
Более того:
Программа, определяющая main как удаленную или объявляющая main встроенной, статической или constexpr, является некорректной.
На практике спецификаций квалификатора noexcept
для main
не существует. С другой стороны, noexcept
можно использовать в качестве спецификатора для любой функции. Это означало бы, что main noexcept
не неправильный формат.
Какая разница без 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
.
person
BiagioF
schedule
30.11.2017
main
, необходимо вызватьstd::terminate
. Если исключение выходит из функцииnoexcept
, необходимо вызватьstd::terminate
. Для всех полезных целейmain
уже естьnoexcept
. И поскольку вы не можете ни вызватьmain
, ни получить на него указатель... какая разница? - person Nicol Bolas   schedule 01.12.2017int main()
иint main() noexcept
дает разные результаты, но я не могу сделать это быстро. Возможно, вы правы, и такого примера вообще нет. - person Constructor   schedule 01.12.2017noexcept
, раскрутка стека никогда не произойдет. В то время как, если вы попытаетесь пробросить черезmain
, может произойти раскручивание стека; это зависит от реализации. - person Nicol Bolas   schedule 01.12.2017noexcept
выполняется раскручивание стека, а безnoexcept
нет . - person Constructor   schedule 01.12.2017noexcept
встречается до того, как был найден обработчик, то стандарт говорит, что вызываетсяstd::terminate
. Я не вижу, где это позволяет реализации вызывать раскручивание до функцииnoexcept
. - person Nicol Bolas   schedule 01.12.2017