How is it that this code seems to work?

B

bobl0456

A student submitted this code:

bool isPalindrome(string word)
{
string::iterator forwardIt = word.begin();
string::reverse_iterator reverseIt = word.rbegin();

while (forwardIt != word.end())
{
if (*forwardIt != *reverseIt)
{
return false;
}
else
{
++forwardIt;
++reverseIt;
}
}
}

The function seems to work, even though I don't believe it should.

Specifically, I believe the code should be instead:

bool isPalindrome(string word)
{
string::iterator forwardIt = word.begin();
string::reverse_iterator reverseIt = word.rbegin();

while (forwardIt != word.end())
{
if (*forwardIt != *reverseIt)
{
return false;
}
else
{
++forwardIt;
++reverseIt;
}
}

return true; // THE CHANGE I MADE
}

The if statement that invokes this function appears to work correctly:

if (isPalindrome(substring))

Does anyone have a clue as to how this works despite the missing return statement?

Thanks in advance.
 
V

Victor Bazarov

Do you understand that compilers *have to* generate the equivalent of
a "return" statement in asm for each subroutine?

That's not true for an inlined function, is it?
They can't just leave
it out because else the execution of the program would just continue
after the last opcode of the subroutine to whatever comes after it,

Which should be just fine for inlined code, shouldn't it?
making the program malfunction? Therefore they can see if there is
an equivalent "return" statement in the source code.
[..]

Just trying to understand...

V
 
A

Alf P. Steinbach

Mr Flibble said:
It is impossible in the general case
for a compiler to emit a diagnostic for missing return statements which
is why it is undefined behaviour instead.
[snip]

What you probably meant was that it's in general impossible to prove
that the execution of a subroutine will ever reach its last 'return'
statement (if it contains previous such statements inside conditionals)

Rather, I think Leigh referred to the case where a non-void function
exits by execution reaching the end of the function body, so that the
return value is dynamically unspecified, which is Undefined Behavior.

The general case includes such code as

auto f()
-> Foo
{ if( fermatsLastTheoremIsTrue() ) { return Foo( 42 ); } }

which a compiler might find difficult to reason about.

The main problem -- for me, who is all I can speak for -- is that in
some cases the compiler *can* prove that execution will never reach a
return statement at the end. Then first without that statement it might
complain that a non-void function, like e.g. throw_exception (I just
call it "fail"), doesn't have a return statement, and then after such a
statement is added the compiler, too smart for the programmer's own
good, complains that the return statement will never be reached...

That's what C++11 "noreturn" attribute is about.

However, as I understand it and vaguely remember it, Visual C++ will
never get C++11 attribute support, but it does have a non-standard
extension (called "declspec") for declaring the same.

I just wrap this, and some other such features, in macros, like
CPPX_NORETURN, defined by a header file that's included via different
include paths for different compilers.


Cheers,

- Alf
 
V

Victor Bazarov

There exists no function you can write that can only be inlined,
from which the compiler does not have to make an actual subroutine
if needed.

Yes, I understand the "if needed" portion. I am just trying to bring it
in concert with the statement that <<compilers *have to* generate the
equivalent of a "return" statement>>. They probably don't *have to* if
the body of the function is inlined, do they? Since the behavior of the
compiler is not mandated in any way (or is it?) the conclusion that they
"have to" is a speculation, yes? I am not trying to argue the point,
just trying to understand.

V
 
S

Stuart

What I meant was that it is undefined behaviour to flow off the end of a
value returning function without using a return statement.

The compiler cannot raise a diagnostic about missing return statements
in the general case as it doesn't always know how a function may be
exited, e.g.:

bool foo()
{
if (bar())
return baz();
wibble();
}

if wibble() always throws an exception then that code is perfectly legal
however the compiler may not be able to determine that wibble() always
throws an exception hence why there is no diagnostic for missing return
statements and flowing off the end is undefined behaviour.

/Flibble

I never thought that this day would come, but in this case I prefer
Java's behaviour. I'd rather be forced to add superfluous return
statements than hunting bugs that stem from forgotten return statements.

However, gcc actually does complain:
1: bool foo () {
2: }

yields

2: "Control reaches end of non-void function"

Regards,
Stuart
 
W

woodbrian77

On Friday, December 13, 2013 5:35:08 PM UTC-6, Mr Flibble wrote:

Please don't swear here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top