Ok so I was messing around on Ideone and accidentally submitted this piece of code, however to my surprise it actually compiled and ran outputting a value of 0, here.
#include <iostream>
using namespace std;
const int five( )
{
const int i = 5;
}
int main() {
cout << five( ) << endl;
return 0;
}
I then tried this in Visual Studio, and on Codepad however both failed to compile because five() does not return a value, as one would expect. My question, is of course, why does this compile fine on Ideone even though the code, to my understanding is wrong and shouldn't compile.
Plain and simply (from C++11 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.
So the compiler is pretty much allowed to do whatever it wants. Clearly, a diagnostic is something I'd prefer from a compiler, but there are times when it can be difficult to diagnose (like when the return is inside conditional logic, and the 'end' of the function would never be reached).
Note that I get the following warning with GCC 4.6.1 (using the Wall option):
test.cpp:8:1: warning: no return statement in function returning non-void [-Wreturn-type]
I'm not sure what options ideone passes to GCC (I imagine that -Wall would do the same with the 4.3.4 version that ideone uses).
Some related information:
In C it's OK for a function that is declared to return a value to not actually do so in certain circumstances; in C it only results in undefined behavior if the function's return value is actually used. Pre-standard C didn't always support the void type, so functions that didn't return anything were often declared to return int, explicitly or implicitly. From C99 6.9.1/12 "Function definitions": If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
Also, as mentioned in a couple comments, flowing off the end of main() is treated specially by C++ and C99 and later.
Not returning a value from a non-void function is a mistake, but not all compiler treats it as an error -- for example, GCC only emits a warning when it encounters this. Other compilers may be paranoid (and they're right) and don't let you compile such code. Of course compiler behavior may be modified using different switches and options.
The return value of 0 is just a random value -- it might equally be 255, -1 or any other garbage, as doing this is undefined behavior (except for main, for which C99 specifies that an implicit 0 return value should be assumed).
It appears that ideone doesn't display warnings, it only displays the compiler output if there was an error. On the version of GCC that ideone is using (gcc 4.3) this isn't an error, it's just a warning.
The code has undefined behavior. Even though what you're doing is wrong, the compiler is not required to diagnose it. The other point is that ideone uses what is now a fairly old version of gcc. A reasonably current version of gcc (e.g., 4.7) will at least give you a warning that your function is declared to return a value, but doesn't -- but not by default. You have to turn it on with something like -Wall to get the warning (but as a general rule, I'd always use at least -Wall with gcc).
Related
Unlike Java, in C/C++ the following is allowed:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
This often causes crashes and it is hard to debug problems. Why doesn't the standard enforce to have a final return for non-void functions? (Compilers generate an error for a wrong return value.)
Is there a flag in GCC or MSVC to enforce this? (something like -Wunused-result)
It is not allowed (undefined behaviour). However, the standard does not require a diagnostic in this case.
The standard doesn't require the last statement to be return because of code like this:
while (true) {
if (condition) return 0;
}
This always returns 0, but a dumb compiler cannot see it. Note that the standard does not mandate smart compilers. A return statement after the while block would be a waste which a dumb compiler would not be able to optimise out. The standard does not want to require the programmer to write waste code just to satisfy a dumb compiler.
g++ -Wall is smart enough to emit a diagnostic on my machine.
Use the -Wall flag in GCC.
warning: control reaches end of non-void function
Or more specifically, -Wreturn-type.
My guess: Because sometimes the programmer knows better than the compiler. With this simple example, it's clear that someting is wrong, but consider a switch of many values, or many checks in general. You, as the coder, know that certain values just will not be passed in to the function, but the compiler doesn't and just hints you, that there might be something wrong.
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
Note that even warning level 1 on MSVC gives the following warning:
warning C4715: 'foo' : not all control paths return a value
You can convert the warning into an error by using the following compiler options
-Wreturn-type -Werror=return-type.
Check out This link
The obvious answer is: because it's not an error. It's only an error if
x is false and if the caller uses the return value, neither of which
can necessarily be determined by the compiler, at least in the general
case.
In this particular case (returning a pointer), it wouldn't be too
difficult to require a return for all paths; Java does this. In
general, however, it's not reasonable in C++ to require this, since in
C++, you can return user defined types for which it may be impossible to
construct a value (no default constructor, etc.) So we have the
situation where the programmer might not be able to provide a return
in a branch that he or she knows can't be taken, and the compiler can't
determine that the branch can't be taken.
Most compilers will warn in such cases, when it can determine the flow.
All of the ones I've seen also warn in some cases where it's clearly
impossible to fall off the end, however. (Both g++ and VC++ warn about:
int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
, at least with the usual options. Although it's quite clear that this
function never falls off the end.)
As far as I remember, Visual Studio 2008 warns you about a "execution path that does not have a return value". It is allowed in the meaning of that "C++ won't stop you from shooting you in the foot". So you are to think, not the compiler.
What the standard says about this kind of programming is that it produces undefined behavior.
Undefined behavior is the joy and pity of C/C++, but it is also a fundamental feature of the language design that allows for many of the low-level optimizations that make C a sort of "high level assembler" (it is not, actually, but just to give you an idea).
So, while redirecting to John's answer about the switch to use with GCC, to know "why" the standard does not prevent that, I would point to a very interesting analysis of undefined behavior and all of its misteries: What Every C Programmer Should Know About Undefined Behavior. It makes for a very instructive reading.
Consider the following example, compiled with g++ 5.4 (only):
#include <iostream>
int foo()
{
std::cout << "foo" << std::endl;
}
int main()
{
std::cout << foo();
return 0;
}
foo() doesn't have any return statement, the code compiles and the function will return an unknown value, same will happen when return type is a pointer - which might cause a segmentation fault.
Why there is no error/warning when compiling such a function?
Is it because of the C++ standard or an issue to implement it?
The language definition says that this produces undefined behavior. That's because it is sometimes not possible to diagnose it. Compilers that warn you about this kind of thing are occasionally wrong. I've added an unneeded return statement to silence one compiler, only to have another complain about that return statement as "unreachable code"
Why there is no error ... when compiling such a function?
Because the program is well-formed. Compilers are required to successfully compile all well-formed programs.
Why there is no ... warning when compiling such a function?
The standard does not require there to be a warning. Old versions of GCC only warn about mistakes like this if you ask the compiler to do so. GCC 8 enabled this particular warning by default.
and the function will return an unknown value
Not quite. The behaviour of the program is undefined if the execution reaches the end of the non-void function without a return, so that may or might not happen.
Note that the function would actually have well defined behaviour in case the stream insertion operator happened to throw or terminated the program. We know that stream insertion is not guaranteed to throw nor to terminate the program, and that it would actually be quite surprising. But the compiler cannot make that kind of generalisations.
I'm using g++ 9.3.0, so can't tell much about g++ 5.4
At older versions, if you have a C++ program missing a return statement from a function that is supposed to return a value, g++ will compile it happily with no errors (or even a warning, unless -Wreturn-type or -Wall or -Werror=return-type is used). Trying to use the return value from the function will most likely cause a segmentation fault.
If you want that behavior, use -Werror=return-type
#include <iostream>
int func(int &a,int &b){
if (a>b){
return 1;
}
}
int main(){
int a=4,b=12;
std::cout<<func(a,b)<<std::endl;
}
I think a run time error should occur because a is smaller than b, and the return statement is skipped. But it actually outputs the value of b no matter how I change the value of b. Could you please tell me why?
it should detect a run time error
That is not the case. The behaviour is undefined.
It seems to be related the value of b, why is that happening?
Because the behaviour is undefined.
This is happening because a result of functions (if the return type is int) is transferred using rax register of CPU. return keyword places its argument in this register and returns to the caller function. But there is also an implicit return keyword at end of any function in C/C++ (if there is no explicit return placed by a programmer). And this is why this function returns control flow to the caller function.
But contents of rax register should be treated in this case as random because the compiler can use it for any variable or even totally ignore it.
Falling out of a non-void function without returning is undefined behaviour, there's nothing your program or the runtime "should" do in that case.
You should not suppress the compiler warnings!
gcc says:
main.cpp:35:1: warning: control reaches end of non-void function [-Wreturn-type].
As others already mentioned: Your program has UB! So read the warnings and fix your program accordingly!
it should detect a run time error
And there is no need for run-time error, as the error is visible during compile-time! The core language has no run-time errors at all. If you see some error messages during program execution, it is coming from library code like a called "terminate" from an exception or something else.
It is good to have all the warnings enabled and also sometimes helpful to run different compilers over the code to get most of warnings possible.
For gcc you could add:
-Wall -pedantic -Wextra
That enables a lot of warnings, but not all. There are still some warnings which are not addressed like: -Wsuggest-override
In C++ if a function is declared to return a value but it doesn't, it is undefined behavior
Turns out that g++ compiler (used in Qt Creator by default) gives a mere warning if you don't have return statement in the non-void function, i.e.:
int* create_array(int n)
{
int* a = new int[n];
}
compiles fine.
This behavior is subject to countless bug reports on g++ itself, but looks like developers consider this behavior conforming to C++ standard (which is debatable, cause it's a bit confusing in this part) as stated at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43943 :
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.
However, the very same paragraph begins with:
A return statement without an expression can be used only in functions
that do not return a value, that is, a function with the return type void,
a constructor (12.1), or a destructor (12.4).
So aside from these (un)holy wars over the standard interpretation are there any options to make Qt flag this as an error at compile time?
This is not related to Qt but to g++.
In the build options, simply add the flag -Werror and g++ will consider any warning as error. You may also need to use flag -Wall to make g++ generate additional warnings, as it doesn't generate warnings for missing return statements (and many other situations) by default. There's no way to tune this setting on a per-warning basis however, so it's either everything or nothing.
You can use -Werror=warning_name syntax to treat a specific warning as an error. For your case you can use -Werror=return-type (where return-type is the name of the "control reaches end of non-void function" warning). According to https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html.
Unlike Java, in C/C++ the following is allowed:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
This often causes crashes and it is hard to debug problems. Why doesn't the standard enforce to have a final return for non-void functions? (Compilers generate an error for a wrong return value.)
Is there a flag in GCC or MSVC to enforce this? (something like -Wunused-result)
It is not allowed (undefined behaviour). However, the standard does not require a diagnostic in this case.
The standard doesn't require the last statement to be return because of code like this:
while (true) {
if (condition) return 0;
}
This always returns 0, but a dumb compiler cannot see it. Note that the standard does not mandate smart compilers. A return statement after the while block would be a waste which a dumb compiler would not be able to optimise out. The standard does not want to require the programmer to write waste code just to satisfy a dumb compiler.
g++ -Wall is smart enough to emit a diagnostic on my machine.
Use the -Wall flag in GCC.
warning: control reaches end of non-void function
Or more specifically, -Wreturn-type.
My guess: Because sometimes the programmer knows better than the compiler. With this simple example, it's clear that someting is wrong, but consider a switch of many values, or many checks in general. You, as the coder, know that certain values just will not be passed in to the function, but the compiler doesn't and just hints you, that there might be something wrong.
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
Note that even warning level 1 on MSVC gives the following warning:
warning C4715: 'foo' : not all control paths return a value
You can convert the warning into an error by using the following compiler options
-Wreturn-type -Werror=return-type.
Check out This link
The obvious answer is: because it's not an error. It's only an error if
x is false and if the caller uses the return value, neither of which
can necessarily be determined by the compiler, at least in the general
case.
In this particular case (returning a pointer), it wouldn't be too
difficult to require a return for all paths; Java does this. In
general, however, it's not reasonable in C++ to require this, since in
C++, you can return user defined types for which it may be impossible to
construct a value (no default constructor, etc.) So we have the
situation where the programmer might not be able to provide a return
in a branch that he or she knows can't be taken, and the compiler can't
determine that the branch can't be taken.
Most compilers will warn in such cases, when it can determine the flow.
All of the ones I've seen also warn in some cases where it's clearly
impossible to fall off the end, however. (Both g++ and VC++ warn about:
int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
, at least with the usual options. Although it's quite clear that this
function never falls off the end.)
As far as I remember, Visual Studio 2008 warns you about a "execution path that does not have a return value". It is allowed in the meaning of that "C++ won't stop you from shooting you in the foot". So you are to think, not the compiler.
What the standard says about this kind of programming is that it produces undefined behavior.
Undefined behavior is the joy and pity of C/C++, but it is also a fundamental feature of the language design that allows for many of the low-level optimizations that make C a sort of "high level assembler" (it is not, actually, but just to give you an idea).
So, while redirecting to John's answer about the switch to use with GCC, to know "why" the standard does not prevent that, I would point to a very interesting analysis of undefined behavior and all of its misteries: What Every C Programmer Should Know About Undefined Behavior. It makes for a very instructive reading.