0

C++ standard says:

The function main shall not be used within a program.

Also:

Recursive calls are permitted, except to the main function.

At the same time C allows such a usage of main according to this answer. I found a comment under that answer that says the following:

The simplest implementation of global constructors (without special support from the OS and underlying C runtime entry code) is for the C++ compiler to generate a function call at the beginning of main (__main is a common name for it) which calls all the global constructors. Having global objects be reconstructed every time main gets called recursively would be a rather bad thing... :-)

It makes sense, but I've tried the following code:

#include <cstdio>

struct S {
    S() { std::puts("S ctor"); }
    ~S() { std::puts("S dtor"); }
};

S s;

int main() {
    static int count = 0;
    count++;
    if (count <= 10) {
        std::printf("%d ", count);
        return main();
    }
    std::puts("");
}

in clang, gcc, msvc. All of these compilers print same output:

S ctor
1 2 3 4 5 6 7 8 9 10 
S dtor

So the global s object was contructed only once despite recursive call of main. Yes, I know what are undefined/unspecified/implementation-defined behaviour mean. But would someone explain (or even demonstrate by code for any available in internet compiler) in more details why using a main function in the C++ program is forbidden and may lead to unexpected results in particular?

αλεχολυτ
  • 4,792
  • 1
  • 35
  • 71
  • 1
    The comment you quote describes *one* way that global constructors could be implemented, and the C++ standard wants to allow implementations that do it that way. But with support from the runtime, it could be done in other ways, e.g. code that calls the constructors before calling `main`. With such an implementation, recursive calls to `main` would work, without calling the constructors repeatedly, and apparently that's how your tested systems work. – Nate Eldredge Dec 19 '20 at 19:31
  • Okay, so the implementation you tried doesn't shove the initialization code into `main` itself (supposedly). Why should the standard prevent that specific implementation technique? – StoryTeller - Unslander Monica Dec 19 '20 at 19:31
  • 1
    A hint for reading the standard: it does not really "forbid". Such clauses should be read as "assuming you are interested in getting a well-defined outcome, then…" — The difference is important, because the standard is built by construction: it starts from a blank slate where you have no guarantee, and then incrementally creates guarantees by imposing the behavior of conforming implementations. Undefined behavior is the norm. The standard only clears some of the undefined in order to carve a space of usable behaviors for conformant programs when compiled by conformant implementations. – spectras Dec 19 '20 at 19:44
  • 3
    Thus your question really should be “why did the standard not constrain implementations into making recursive calls to main() well-defined"? From which you can infer the benefit probably was not worth the cost (how useful such a guarantee would be for programs vs how constraining such a guarantee would be for implementations). – spectras Dec 19 '20 at 19:47

0 Answers0