tags:

views:

598

answers:

10

Hi, 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?

+17  A: 

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.

GMan
Do you have a reference for this supposed illegality? I doubt if compilers are required to detect this.
ergosys
@ego: It's in the post. :o
GMan
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
@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
@Swiss You do not run it, but the C++ implementation and its infrastructure does. Check the pointed section in the standard.
mloskot
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
@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.)
GMan
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`.
GMan
@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
@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
I've addressed the confusion in this post: http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c/2128727#2128727
GMan
@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
A: 

compiler error...

GK
+4  A: 

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
+2  A: 

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
True for any other function, but calling main is not allowed.
jalf
and yet, the compiler allowed it. I think this term 'not allowed' means something other that what you think it means...
John Knoeller
@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.
GMan
John*, not "Jogn"; my bad.
GMan
@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
@John, i think you are misunderstanding the Standard then. What the Standard states is pretty clear, and it forbids calling `main`.
Johannes Schaub - litb
@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? :]
GMan
@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
I'm not sure I understand your last comment, sorry. Could you rephrase it?
GMan
@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
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.
GMan
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.
GMan
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.
GMan
@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
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
@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.
GMan
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.
GMan
@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
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.
GMan
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.
GMan
@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
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
@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
@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.
GMan
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.
GMan
"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
@MSalters: precisely my point, they are _capable_ of it, and yet they don't.
John Knoeller
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
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
@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?)
GMan
+4  A: 

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
A: 

I would also like to know the compiler. Under gcc/g++ the program compiles but I get a segmentation fault when running the program.

J. Polak
g++ -Wall -c "%f"
skydoor
It doesn't show but as mentioned above -pedantic does with the output "error: ISO C++ forbids taking address of function ‘::main’"
J. Polak
+2  A: 

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

alemjerus
+1 for making me laugh. :)
Matteo Italia
+1  A: 

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
+7  A: 

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.

GMan
In VS, you can change your entry point to function like ThisIsMyNewMainAndBeatIt(), then you can call main() again and feel good with it.
alemjerus
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
@Johannes: I thought "anything can happen" was a run-time issue, while at compile time a diagnosis should be required.
GMan
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
@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
@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. :]
GMan
+1  A: 

Of course if you really want call your main function recursively, and sometimes there are good reasons, you should just do this

int mymain()
{
  mymain();
}

int main()
{
   mymain();
}
Michael Anderson