可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I recently wrote a post:
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!!
回答1:
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.
回答2:
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.
回答3:
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...'.
回答4:
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.
回答5:
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.
回答6:
"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++.