Рекурсивный вызов main

107
04 июня 2019, 15:50

Что будет при рекурсивном вызове функции main???

int main() {
  main();
}
Answer 1

Стандарт запрещает использовать функцию main

6.6.1 main function
3. The function main shall not be used within a program. ...

Однако, некоторые компиляторы могут отклоняться от стандартного поведения.

К примеру, возьмем clang 3.8.0.
С флагом -pedantic-errors компилятор выдает ошибку:

error: ISO C++ does not allow 'main' to be used by a program

https://rextester.com/QBKCG46413

Однако, если убрать данную опцию, то поведение, возможно, будет неожиданным. Возьмем небольшой код:

#include <iostream>
struct Some
{
    Some() { std::cout << "begin" << std::endl; }
    ~Some() { std::cout << "end" << std::endl; }
};
Some s;
int main()
{
    main();
}

Объект s предназначен просто для вывода сообщений до запуска main и после её выполнения.

Если собрать это с флагом -O0, то получаем честный SIGSEGV: https://rextester.com/XTRATW71243

Однако, уже с флагом -O1 мы видим вывод обоих сообщений и никаких ошибок

begin
end

т.е. main выполнился успешно: https://rextester.com/XUF23687

Это связано с оптимизациями при неопределенном поведении. Дело в том, что бесконечная рекурсия без изменения состояния - неопределенное поведение, поэтому компилятор вправе сделать что угодно. В данном случае clang видит, что рекурсия не меняет внешнее состояние, и имеется всего одна точка выхода - return 0 в конце main (будет добавлен компилятором автоматически, т.к. в main отсутствует явный return), поэтому всю эту рекурсию можно законно удалить:

4.6 Program execution
1. The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.6
...
6) This provision is sometimes called the “as-if” rule, because an implementation is free to disregard any requirement of this International Standard as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program. For instance, an actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no side effects affecting the observable behavior of the program are produced.

Если посмотреть код функции main после компиляции, то он таков:

main:                                   # @main
        xor     eax, eax
        ret

https://godbolt.org/z/63h1rn

Answer 2

Стандартом языка запрещается любое использование функции main:

6.6.1 main function [basic.start.main]
3 The function main shall not be used within a program.

Answer 3

Переполнение стека, поскольку нет никакого условия завершения рекурсии...

Кстати, VC++ 2017, например, честно об этом предупреждает. А вот GCC на ideone компилирует без предупреждений.

Answer 4

Функция main обладает следующими специальными свойствами:

  1. Она нигде не может быть использована в программе,
    • в частности её нельзя вызывать рекурсивно;
    • нельзя взять её адрес.
  2. Её нельзя объявлять и нельзя перегружать: фактически имя main зарезервировано в глобальном пространстве имён для функций (хотя это имя может быть использовано для именования классов, пространства имён, перечислений и любых сущностей не в глобальных пространствах имён, за исключением того, что функция с именем 'main' не может быть объявлена со связыванием для языка C в любом пространстве имён (начиная с C++17)).
  3. Её нельзя объявить как удалённую или определить со связыванием для C (начиная с C++17), inline, static или constexpr.
  4. В теле функции main не обязателен оператор return: при завершении функции main без оператора return эффект будет тот же самый, как при выполнении return 0;.
  5. Выполнение return (или неявного return при достижении конца функции main) эквивалентно нормальному выходу из функции (которое уничтожает объекты с автоматическим временем жизни) с последующим вызовом std::exit с тем же самым аргументом, который был передан в return. (std::exit уничтожает статические объекты и завершает программу).
  6. Если функция main определена как function-try-block, исключения, брошенные деструкторами статических объектов (которые уничтожаются при вызове std::exit), не отлавливаются функцией.
  7. (начиная с C++14) Тип возвращаемого значения функцией main не может быть выведен (auto main() {...} не разрешён).

https://ru.cppreference.com/w/cpp/language/main_function https://en.cppreference.com/w/cpp/language/main_function

READ ALSO
Изменить кодировку символа в C++

Изменить кодировку символа в C++

Так уж пришлось, что мне нужно сделать задание в C++ builder 6И такой вопрос, как изменить маленькую букву на большую через изменение кода символа

133
Ошибка в передаче аргумента в функцию

Ошибка в передаче аргумента в функцию

Есть ошибка, cmap передается в такую фукнцию

131
Не работает fstream C++

Не работает fstream C++

Изучаю работу с файлами в С++ Сделал абсолютно все как в примереВ консоль выводится сообщение Good!, но при этом файл не создается, а если вручную...

159
Проблема с заменой в com порте

Проблема с заменой в com порте

Такая проблема, есть команда которая вводится в cmd:

154