What (actually) happens, when a function with the warning "control reaches end of non-void function" is called?

I know what this message means, I just wondered why it is not an error message, but just a warning?

What happens in this case? For example, suppose I have a function

int f()
{
}

and what happens when I call it?
Does the compiler adds returning of "non-initialized" int in this case?
Or the missing return could cause stack corruption?
Or it's (absolutely) undefined behavior ?

Tested with gcc 4.1.2 and 4.4.3


EDIT: Reading the answers I understand one thing, reading the comments - another..

OK, let's summarize: it's undefined behavior. Then, this means, that it is possible to result in stack corruption, right? (it even means, that my computer may start throwing rotten tomatoes over me through the mic jack, screaming - "what have you done???").

But if so, then why the top answer here says, that stack corruption can't happen and, in the same time, that the behaviour is undefined?

And undefined in respect to? The caller, that tries to use the "not returned value", or just the end of the function is undefined, if it must return value, but it doesn't?

Or it's not undefined behavior, and just the user, who tries to use the value (that is not returned, d'oh!) will "receive" undefined value? In other words - just some garbage value and nothing more can happen?


Solution 1:

A: No, the missing return would not cause stack corruption

A: Yes, the behavior would be "undefined" if the caller tried to read and/or use the (undefined!) return value.

PS:

Here's a citation for C++:

C++03 §6.6.3/2:

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

Solution 2:

You asked about both C and C++. The rules are different in the two languages.

In C, the behavior is undefined only if the caller attempts to use the value returned by the function. If you have:

int func(void) {
    /* no return statement */
}

...

func();

then the behavior is well defined.

In C++, the behavior is undefined (if the function is called at all) whether the caller attempts to use the result or not. (This is for historical reasons; pre-ANSI C didn't have the void keyword, and functions that were not intended to return a value were commonly defined (implicitly) to return int.)

John Bode's answer already quoted the N1570 draft of the 2011 ISO C standard, 6.9.1p12:

If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

And paulsm4 cited the C++ standard; quoting the latest 2011 version, 6.6.3p2:

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

The historical reasons that led to C permitting a value-returning function to fail to return a value, as long as the value is not used by the caller, do not apply to C++, whose design was not as strongly influenced by the need to avoid breaking old (pre-ANSI C) code.

In both C (starting with C99) and C++, the main function is a special case; reaching the closing } of main without executing a return is equivalent to a return 0;. (C permits main to return an implementation-defined type other than int; in that (rare) case, falling off the end returns an unspecified termination status to the host environment.)

Of course omitting the return statement from a value-returning function, or having a possible execution path that doesn't reach a return statement, is a bad idea. It makes sense only in ancient legacy C code that uses int as a stand-in for void, and in main (though even for main, I personally like to have an explicit return 0;).