17

Can anybody tell what's the problem of the code below?

int main () { 
    return main(); 
}

I tested, it compiles correctly. It's running forever. Anymore trick behind the scene?

jww
  • 97,681
  • 90
  • 411
  • 885
skydoor
  • 25,218
  • 52
  • 147
  • 201
  • 6
    Don't worry, it won't run forever. The second the stack overflows, it'll tell you all about it. Have you considered tail recursion? – ojrac Jan 24 '10 at 19:12
  • 7
    @ojrac The function `main` as defined **is** tail-recursive and was obviously optimized as such by the compiler. If it was going to overflow the stack, it would do so quickly (for instance on my platform `stack size (kbytes, -s) 8192` ) – Pascal Cuoq Jan 24 '10 at 19:17
  • 1
    Thanks for the sense of humor, @Pascal. :) – ojrac Jan 24 '10 at 19:19
  • 7
    *"Can anybody tell what's the problem of the code below? "* We could, but not until you tell us what's the problem with that code is. – dmckee --- ex-moderator kitten Jan 24 '10 at 19:37
  • 8
    For any utterance you may unleash on the internet with humorous intent, there are a thousand people, also on the internet, who would say the exact same thing sincerely — Feel free to quote this as the law of Pascal. – Pascal Cuoq Jan 24 '10 at 20:10
  • 9
    To understand recursion, you must first understand recursion. –  Sep 06 '11 at 22:50
  • Possible duplicate of [Is it legal to recurse into main() in C++?](https://stackoverflow.com/questions/4518598/is-it-legal-to-recurse-into-main-in-c) – ks1322 Apr 10 '18 at 12:05

9 Answers9

42

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.

jww
  • 97,681
  • 90
  • 411
  • 885
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 2
    In VS, you can change your entry point to function like ThisIsMyNewMainAndBeatIt(), then you can call main() again and feel good with it. – alemjerus Jan 24 '10 at 21:06
  • Your use of "undefined behavior" does not match the rest of the world, it seems. That may be fine but i think it deserves an explanation. What you seem to mean is that the compiler is free to do what it wants after giving at least one diagnostic (this of course is always the case, even for a correct program: The standard does not forbid compressing the result executable, for instance). But what most other people mean is that *anything* can happen, including no diagnostic at all. So, calling main is equivalent with writing "i have a dream" into your main function: It's just ill-formed. – Johannes Schaub - litb Jan 24 '10 at 22:11
  • @Johannes: I thought "anything can happen" was a run-time issue, while at compile time a diagnosis should be required. – GManNickG Jan 24 '10 at 22:14
  • Fair point. I agree with you: Once the compiler accepts the code (after giving a diagnostic), it will probably do the obvious thing and cause infinite recursion which indeed is bad. Just wanted to note that on the language level, this is really not different from writing other ill-formed snippets, like `int *i = 10;`. What the compiler does in the end is its business. Have fun :) – Johannes Schaub - litb Jan 24 '10 at 22:19
  • @GMan regarding your last question about whether undefined behavior is only a runtime issue. "Undefined behavior" is about both translation and execution. Some cases where UB is a compile time issue: Unbound template instantiation, forgotten newline in non-empty file, violation of ODR (two different definitions of the same class). I think exceeding limits also causes undefined behavior (like too many nested blocks, too long identifiers, etc..). – Johannes Schaub - litb Jan 24 '10 at 22:51
  • @Johannes: Okay, that makes more sense. I thought more about driving to work and what you said "clicked" and made sense. Thanks for your input. :] – GManNickG Jan 24 '10 at 23:45
  • 1
    +1 for repeating *"the standard alone determines everything about the C++ language."*. People often forget this! – Nawaz Jan 18 '11 at 06:04
  • 1
    "undefined behavior"? Hardly, just ill-formed program. And while the compiler need not reject ill-formed programs, it must most certainly diagnose them. – Deduplicator Feb 22 '15 at 16:48
  • "The function main shall not be used within a program." seems to imply even converting the address of `main()` to an integer or attempting to print it is UB. – chux - Reinstate Monica Mar 07 '16 at 21:13
  • @chux: Yes, as mentioned in the answer attempting to take the address of main is also not allowed. – GManNickG Mar 07 '16 at 22:22
24

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.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • Do you have a reference for this supposed illegality? I doubt if compilers are required to detect this. – ergosys Jan 24 '10 at 19:19
  • 4
    I find this rule amusing in its ambiguity. "How am I supposed to get my program to run if I can't use main?" – Swiss Jan 24 '10 at 19:21
  • @GMan The note about compiler is allowing illegal behaviour is not precise. The standard does not require compiler to perform any diagnostics. So it is not required to throw any error message. – mloskot Jan 24 '10 at 19:23
  • 1
    @Swiss You do not run it, but the C++ implementation and its infrastructure does. Check the pointed section in the standard. – mloskot Jan 24 '10 at 19:24
  • He never said it needed either, just that it was not allowed. I do not have the standard but I guess that would invoke undefined behaviour? – Skurmedel Jan 24 '10 at 19:29
  • @Swiss: It says within the program itself. @mloskot @ergosys: I am well aware the standard says nothing on how pedantic compilers must be. I merely said this particular compiler the OP is using allows illegal behavior, as opposed to stops illegal behavior. @Skurmedel: If a program does something the standard prohibits, it technically makes it undefined behavior. (For the behavior is not defined.) – GManNickG Jan 24 '10 at 19:35
  • If you use `-pedantic` with gcc, it warns about calling `main`. Visual Studio will warn about the recursion with warnings on (any level), but does not care about calling `main`. – GManNickG Jan 24 '10 at 19:41
  • @mloskot, if the standard says "shall not", that means that a diagnostic is required in C++. It says: "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.”" "If a program contains a violation of any diagnosable rule, a conforming implementation shall issue at least one diagnostic message" – Johannes Schaub - litb Jan 24 '10 at 20:27
  • @Swiss, "used" refers to the term *used* defined at 3.2/2 in the one definition rule. But please notice GCC's wrong behavior, posted here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41431 – Johannes Schaub - litb Jan 24 '10 at 20:31
  • I've addressed the confusion in this post: http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c/2128727#2128727 – GManNickG Jan 24 '10 at 20:57
  • @Johannes Schaub I admit you and GMan was right. I messed with C standard a bit in understanding the rules specified about main function. – mloskot Jan 24 '10 at 23:06
14

It's like being a drug-dealer. Pretty illegal, but compiles and even works out good for some time...

alemjerus
  • 8,023
  • 3
  • 32
  • 40
7

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();
}
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
5

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.

Randolpho
  • 55,384
  • 17
  • 145
  • 179
5

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.

mloskot
  • 37,086
  • 11
  • 109
  • 136
3

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.

John Knoeller
  • 33,512
  • 4
  • 61
  • 92
  • 2
    True for any other function, but calling main is not allowed. – jalf Jan 24 '10 at 19:37
  • and yet, the compiler allowed it. I think this term 'not allowed' means something other that what you think it means... – John Knoeller Jan 24 '10 at 19:43
  • 4
    @Jogn: Just because one compiler doesn't stop something doesn't suddenly make it allowed, defined, etc. **The language is specified by the standard and the standard alone.** And the standard says it's not allowed. It's as simple as that. – GManNickG Jan 24 '10 at 19:53
  • @Gman. The spec doesn't say that the user can't call main, it merely says that the _compiler_ can't use 'main' for anything other than it's stated purpose. I can think of no use for calling main recursively, but it just a function, it would be pointless for a compiler to actually _prevent_ me from calling it. – John Knoeller Jan 24 '10 at 20:20
  • 3
    @John, i think you are misunderstanding the Standard then. What the Standard states is pretty clear, and it forbids calling `main`. – Johannes Schaub - litb Jan 24 '10 at 20:34
  • @John: I have addressed the confusion here: http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c/2128727#2128727 @litb specifically: Can you please correct any terms I'm mis-using? :] – GManNickG Jan 24 '10 at 20:43
  • @gman: When I want to know what code does, I don't look at the comments. I look at the code. So, while I buy your argument in the absence of a compiler to test it against, we don't lack compilers to test it against. – John Knoeller Jan 24 '10 at 20:52
  • I'm not sure I understand your last comment, sorry. Could you rephrase it? – GManNickG Jan 24 '10 at 20:55
  • @Gman: Compiler writers read the spec _very carefully_. I trust their interpretation (as demonstrated by the behavior of the compiler) over yours. Your interpretation seems reasonable, but if it was _correct_, then skydoor would not have seen his program "run forever". – John Knoeller Jan 24 '10 at 21:06
  • 1
    Once again, you're misunderstanding the purpose of the compiler. Did you read my newer post? (It's the community wiki one that got accepted.) There does not exist a single compiler that 100% accurately implements the C++ language! My interpretation is exactly correct in accordance to the definitions defined within the standard. There simply isn't an argument here, you're arguing that while 2 + 2 is defined to be 4, some compiler says it's 5, so it must be 5. – GManNickG Jan 24 '10 at 21:36
  • Again, my interpretation is correct. Your logic is as follows: Compilers implement the standard 100% correctly. This behavior is allowed by that compiler. Therefore, the behavior is 100% correct. This logic is *valid* but it is *not sound*! The reason is simple: Compilers do not implement the standard 100% correctly. Seriously, every definition is there for you to read, don't take my word for it, read it yourself. I've done the reading for you in the aforementioned post, with quotes, so you know I'm not lying or anything. You're arguing a lost cause. – GManNickG Jan 24 '10 at 21:38
  • We are all well aware compiler implementors read the standard carefully. But it's not hard to find proof of incorrectness. For example, it is 100% legal according to the standard to take the address of `main`, yet we have: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41431 Does this somehow make the standard wrong? Does it imply it's actually illegal to take the address of `main`? No and no. – GManNickG Jan 24 '10 at 21:40
  • @Gman: I'm not sure why you're so hot about this, but you misstate my argument. I'm not saying compilers are perfect, I'm saying that I take their interpretation of the spec over yours. And also, that _I don't care_ what the spec says. What matters is what the compiler _does_. WE don't compile our code with specs. – John Knoeller Jan 24 '10 at 21:54
  • Also, go back and read the question. He wanted to know why he was seeing what he was seeing. Telling him that his code should not compile was _completely unhelpful_. Especially when it was clear that the code _did_ compile. – John Knoeller Jan 24 '10 at 21:59
  • 1
    @John: I'm not hot. Maybe if I threw in a few ":)" it would be more obvious. I rarely get heated in arguments, due to irrelevant things. I guess we have a lost argument then. The question at hand is "is this allowed?", and the answer is no. The question wasn't "does my compiler allow this?" My interpretation (which is misleading, as it's **the** interpretation) is correct. Sorry. In honesty, when talking about correctness in a language, the "it works on my compiler" attitude is probably the worse position to take. Compilers simply don't determine correctness. – GManNickG Jan 24 '10 at 21:59
  • Also, it's hardly unhelpful. Telling him his code is **undefined behavior** is the only truthful answer. The behavior is **undefined**, ergo any answer that tries to *define* the undefined behavior is being blatantly foolish. – GManNickG Jan 24 '10 at 21:59
  • @Gman: No, his problem was infinite recursion, it had nothing at all to do with undefined behavior. Main behaves exactly the same way as any other function, it would be _bizarre_ if the spec mandated that it didn't, which you seem to be arguing. – John Knoeller Jan 24 '10 at 22:04
  • It's not bizarre, it's *right there*, black and white, clear as crystal. (Charlie and the Chocolate Factory reference, hehe). It is unarguably 100% *undefined* behavior, which means you nor anybody can *expect* any certain behavior to come about. You're essentially defining undefined behavior. That's like saying "x / 0 = 1". It's nonsensical. – GManNickG Jan 24 '10 at 22:07
  • Before I go, I should point out in that my points above were in response to "and yet, the compiler allowed it. I think this term 'not allowed' means something other that what you think it means...", not the OP's question. – GManNickG Jan 24 '10 at 22:19
  • 2
    @John: Undefined behavior has *everything* to do with the infinite recursion he's seeing. Calling main behaves exactly the way the compiler implements it. Which is not necessarily the same way as any other function. And the spec mandates **nothing**, unlike what *you* seem to be arguing. You're arguing that the spec should require main to behave like any other function when called. The spec does not guarantee that. And for heaven's sake, **never** trust the compiler over someone who simply reads the spec. The compiler writers carefully read the spec, yes, but they may choose not to follow it. – jalf Jan 24 '10 at 23:41
  • 1. The c/C++ runtime is written in C/C++ 2. it is impossible to implement the C runtime without calling main somewhere in it. 3. Profit – John Knoeller Jan 25 '10 at 01:05
  • @jalf: the spec doesn't say that you can't call main in your program, it says you cant 'use' main in your program. Which you interpret (incorrectly) to _mean_ call. But since there is no such thing as a compiler that prohibits you from calling main, 'use' must mean something else. Being pedantic and _wrong_ is the very definition of being unhelpful. – John Knoeller Jan 25 '10 at 02:06
  • 2
    @John: No one is going to take you seriously. Just read this post http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c/2128727#2128727 and understand the *very well defined terminology used*. "Use" was also defined there. We are correct, everything is *right there* in the standard for you to read. It's sheer laziness to not just look it up yourself and continue arguing with your own predisposed definitions. I normally don't down-vote answers based on comments, because they are two separate things, but here you go. You're spreading misinformation. – GManNickG Jan 25 '10 at 02:52
  • 1
    C++ is defined by the standard. That's the final word. No compiler defines the language, no compiler implementers interpretation (which you don't even know, because you only know:), compilers choice of implementation, etc. Nothing else, only the definitions and words in the standard. I'm done. If you choose to continue being ignorant, so be it, but refrain from trying to talk about the C++ language if you refuse to consult the C++ standard. – GManNickG Jan 25 '10 at 02:54
  • "There's no such thing as a compiler that prohibits you from calling main" - since each and every function call is put in my executable by a compiler, they are entirely capable of not putting in calls to main(). – MSalters Jan 25 '10 at 12:49
  • @MSalters: precisely my point, they are _capable_ of it, and yet they don't. – John Knoeller Jan 25 '10 at 20:00
  • 1
    Yes, they don't. Because they are not allowed. The Standard forbids. If they do it anyway without telling you about it, they are not conformant. And GCC is not conformant. @GMan, anyway trying to call `main` is *not* undefined behavior - it is **ill-formed**. That's way different: If it was undefined, GCC would be alright being quite about the try to call. – Johannes Schaub - litb Jan 26 '10 at 17:29
  • If you arrange it so that the second time you would enter `main` body you would return immediately (let's say using a static variable), you cannot even argue that it is "undefined behavior if the call would be allowed after giving a diagnostic". Anyway, using the term "undefined behavior" in that sense is very confusing, in my opinion, because it then is not equal to the C++'s notion of it, but just to a general english term. The same way you could say compiling a program is "undefined behavior", because you don't know the size of the resulting executable. Just my two cents :) – Johannes Schaub - litb Jan 26 '10 at 17:39
  • @Johannes: I see how that would make it not undefined behavior directly, so I'll say I was mis-using the term. But certainly doing something not defined (because it shouldn't happen) is some form of undefined behavior? Or perhaps that's the execution? (IIRC, an ill-formed program *may* result in undefined behavior?) – GManNickG Jan 26 '10 at 18:14
2

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
}
CashCow
  • 30,981
  • 5
  • 61
  • 92
1

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.

HerbN
  • 1,509
  • 12
  • 23