views:

196

answers:

6

Hi Everyone,
I recently wrote a post:
http://stackoverflow.com/questions/3452355/weird-error-in-c-program-removing-printout-breaks-program

...in which I was trying to solve a seemingly baffling problem, in which removing a cout statement would break my program.

As it turned out, my problem was that I forgot to return my true/false success flag that I was later using for logic.

But apparently SOMETHING was being returned and that something was always true if I left that cout in, but would seemingly "magically" become false when I took it out.

My question for you all is:
What determines what a c++ function return when no return command is executed within the function? Is there any logic to it?

Obviously forgetting your return type is a bad idea. In this case, though, it was largely due to the nature of my program -- a quick hack job. I later decided that it wasn't worth the effort to include implement an algorithm to determine the success/failure of the function call -- but accidentally left behind the code dependent on the return.

Bafflingly g++ gave me no warnings or errors when compiling the executable like so:

g++ main.cc -g -o it_util

My version is: g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)

Again, to save others future frustration in case they make the same silly mistake and are met with the same seemingly erratic behavior, can anyone cast light on where a function without a return gets its return value from??

Thanks!!

+4  A: 

There is no logic to it, and most C++ compilers should flag it with a warning. It allowed for backward-compatibility to C.

In K&R C, there was no void type, and when a type was unspecified, it default to int. So,

myfunc() {....}

Was techincally a function returning a int, but most programmers used that form for a routine not returning a value.

The compiler had to make sense of this. So, the convention became, the return would put something into a register. And the assignment in the calling routine would take the value out of the register. Now, if the callee never issued a return, nothing specific would be placed in that register. But it would still have some (random) value in it, which would be blindly assigned in the caller.

James Curran
+1  A: 

It depends on the calling convention. For instance, for a 32-bit integer return on an Intel platform, you get whatever is in the eax register.

grddev
+3  A: 

From C++ Standard section 6.6.3 The return statement

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.

There is one exception (as per 3.6.1/5):

If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;

The reason this is syntactically allowed is put nicely by James Curran. But with the -Wall gcc option (as commented by Neil) you should be warned on this behavior; something like 'Not all control paths return value in a value-returning function...'.

Abhay
Is there any case where this is desirable behavior in modern c++? Why is there no warning by default (i.e. why do you have to turn on -Wall in g++ to see the error?)?
Jason R. Mick
@Jason: Imagine you have a template function `template<class T> T func() { return ; } template<> int func() { return 1; } template<class T> T func1() { return func<T>(); } int main() { func<void>(); func<int>(); return 0; }` Now the compiler cannot complain based just on the `return` keyword, can it ?
Abhay
@Jason: g++ gives no warnings by default. That's just the way it is.
Mike Seymour
There is one exception (3.6.1/5): If control reaches the end of `main` without encountering a `return` statement, the effect is that of executing `return 0;`.
Mike Seymour
@Mike: Your r right. Edited to include the exception.
Abhay
+2  A: 

On x86 calling conventions, the return value for integers and pointers is on the EAX register. The following is an example of that:

int func() {
    if(0) return 5; // otherwise error C4716: 'func' : must return a value
}
int main() {
    int a;
    a = func();
}

Compiling with cl.exe /Zi, MSVC++10:

push    ebp
mov     ebp, esp
push    ecx
call    j_?func@@YAHXZ  ; func(void)
mov     [ebp+a], eax ; assumes eax contains the return value
xor     eax, eax
mov     esp, ebp
pop     ebp
retn

Of course, this is all undefined behavior.

Pedro d'Aquino
A: 

With a modern compiler you'll probably get an Warning using -Wall

But if you don't return a value, usually you'll get garbage.

ppaulojr
A: 

"What determines what a c++ function return when no return command is executed within the function? Is there any logic to it?"

The type in the beginning of the function.

Example:

int cow() { int temp; return temp; }

If you don't return the correct type or return nothing, the compiler should complain. Edit: Oh crap, I've just read your flags. You need to turn on more flags man, -W -Wall -pedantic. Read the g++ manual.

Unless you have a void function. Then you don't have to return anything or you can have pointer to play.

void somefunction( int* ptr_int) { int temp = *ptr_int; temp +=1000; this->ptr_int = temp; }

I believe the above code works, it have been awhile since I've coded in C++.

mythicalprogrammer