Can anybody tell what's the problem of the code below?
开发者_Python百科int main () {
return main();
}
I tested, it compiles correctly. It's running forever. Anymore trick behind the scene?
TLDR: Calling main
results in undefined behavior.
There seems to be confusion about the terminology used in the standard, and the implications that has for the programmer and compiler.
Firstly, the standard alone determines everything about the C++ language. If your particular version of a particular compiler allows some particular action, that has no bearing on whether or not that action is legal. For the remainder of the post, I'm referring to the ISO03 standard.
So to quote once again, the standard says in §3.6.1.3:
The function main shall not be used within a program.
Additionally, §3.2 defines "used" as:
An object or non-overloaded function is used if its name appears in a potentially-evaluated expression.
This means that once the program begins executing, main
should never be entered again. That means programmers cannot call main
, that means the compiler cannot insert another call to main
(why it would, who knows), you cannot take the address of main and call that, etc. You cannot even have the potential of calling main
.
The only call to main
should be by the run-time library the program is running on; all other calls invoke undefined behavior. (Which means anything could happen!)
Now onto compiler behavior:
A diagnosable rule is defined as (§1.4.1):
The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior.”
In our case, §3.6.1.3 defines a diagnosable rule. Here's what compilers should do according to §1.4.2:
— If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute3) that program.
— If a program contains a violation of any diagnosable rule, a conforming implementation shall issue at least one diagnostic message, except that
— If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.
So compilers are not required to enforce rules. All compilers have to do is take well-formed programs (§1.3.14) and turn them into an executable program. A compiler is free to warn, error, etc. however it likes, as long as it does not conflict with the language. It is required to display a message in our particular case, according to the second clause.
For this particular problem, on gcc the -pedantic
option will warn about the illegality of calling main
within the program. Visual Studio will not warn about calling main
, but on any warning level (greater than 0) it will warn about the recursive nature of the program.
What does all this mean in terms of the answers you should expect? It means it's completely meaningless to try and define with certainty what the code snippet posted will do. Calling main
results in undefined behavior, and trying to define undefined behavior is obviously a lost cause. The only honest answer anyone can give to "what happens when I call main
?" is "Anything."
I hope this clears things up.
Calling main
in C++ is illegal (§3.6.1.3):
The function main shall not be used within a program.
Your compiler is allowing illegal behavior.
It loops forever because, well, main
calls main
, who calls main
, who calls main
, and so on.
It's like being a drug-dealer. Pretty illegal, but compiles and even works out good for some time...
Of course if you really want call your main function recursively, and sometimes there are good reasons, you should just do this
int mymain()
{
return mymain();
}
int main()
{
return mymain();
}
The question is, why would you want to?
main is supposed to be a single entrypoint for your program. Calling it again essentially restarts your program, but without a new process instance; no new stack, no new heap, etc.
If you really need recursion, call a separate function recursively.
The C++ standard, in section 3.6.1 it says:
The function main shall not be used (3.2) within a program.
It specifies, you are not supposed to call it from within your program.
When you write recursive code, you need to make sure that at some point you stop recursing, otherwise you've just written an infinite loop.
Which you have.
You should expect this code to go away for a long time and then finally crash with a stack overflow.
Whilst your program obviously makes no sense as it loops forever it might look feasible to do something like:
int main( int argc, char* argv[] )
{
if( argc )
{
// do something with argv[0]
main( argc - 1, &argv[1] );
}
else
{
// rest of application having loaded your arguments
}
}
However the standard disallows it. (See other answers)
Of course you can implement that by doing this
int myFunc( int argc, char * argv[] )
{
// I can recurse this if I like and just get main to forward straight to here
}
You have two issues. The first is calling main which, as has been pointed out both violates the standard and the intent of the standard.
The bigger problem is you've written a recursive call without any closing point. You question seems to assume that the version of main called by the initial one will just return. However, most languages (in fact all I can think of) allowed unlimited recursion: if a function calls itself then that version will as well. The only limit is system resources.
So you need to wrap the call in a conditional and only continue to call when needed. In your example, adding a global integer set to the number of levels you want to recurse would work. Something like this:
`
int levels = 3;
int main() {
if(levels) {
cout << "Recursing another level...\n";
levels--;
main();
}
else {
cout << "Reached the bottom.\n";
}
return levels;
}
`
Will exit.
精彩评论