Jump to content
  • Advertisement
Sign in to follow this  
load_bitmap_file

C++ - When not all paths lead to a return?

This topic is 4926 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Quote:
You are lucky compilers add a return statement at the end of functions at all. Otherwise your code would continue to execute whatever code follows that function.

I don't know what the C/C++ standard on this is, but just imagine what might have happened if the compiler didn't return at all


Yeah, like the good ol' assembler days [sick]

Share this post


Link to post
Share on other sites
Advertisement
First of all, you should be getting a warning. Secondly, in debug mode it will initialize registers and memory to very specific values. Most likely 0xCCCCCCCC or 0xCDCDCDCD, although there are a few other values it uses as well.

This doesn't happen in release mode, and hence whatever is in eax is what you get. Using the pragma to convert the warning to an error is recommended.

Sheeva: the rules are vastly different. C++ is a much more complex language than C#, and C# is much stricter in it's application of it's rules. What might constitute "implementation specified" behavior in C++ constitutes erroronious behavior in C#. Just because they both start with a C doesn't mean they behave the same.

As for your switch statement, what if the value isn't Yes or No? You do realize that you can cast an arbitrary integer to an enumeration, and it is perfectly legal for the value to not be in the range of those provided by the enumeration. For instance, your code would break on this func((Answer)2);. However, that is a perfectly legal call. Thus not all paths DO return a value, hence you either need to insert a default case that throws (the best idea) or just add an additional return statement.

Share this post


Link to post
Share on other sites
Quote:
Sheeva: the rules are vastly different. C++ is a much more complex language than C#, and C# is much stricter in it's application of it's rules. What might constitute "implementation specified" behavior in C++ constitutes erroronious behavior in C#. Just because they both start with a C doesn't mean they behave the same.

That's not what I meant. What I meant is that C++ .NET and C# are (or at least could) be used together in managed applications, and so their behavior should be at least similar to my mind.
Quote:
As for your switch statement, what if the value isn't Yes or No?

OK, OK, that was a stupid example. I wanted to show the choice of some known values (or states, or anything), when we do handle all of the possible values.
Quote:
You do realize that you can cast an arbitrary integer to an enumeration

Yeah, C++ allows you to cope with lots of things that are logically wrong, like such casting to yes/no. Take the pointer juggling to get access to private members of a class for instance. That doesn't mean you must do each and every function so foolproof.
Quote:
you either need to insert a default case that throws (the best idea) or just add an additional return statement.

Since the problem is probably logical, and you shouldn't go and cast random ints to enums around, it isn't necessary to throw, and the additional return statement is pointless, too (in this particular case)

Share this post


Link to post
Share on other sites
Quote:
Original post by Sheeva_
Quote:
Sheeva: the rules are vastly different. C++ is a much more complex language than C#, and C# is much stricter in it's application of it's rules. What might constitute "implementation specified" behavior in C++ constitutes erroronious behavior in C#. Just because they both start with a C doesn't mean they behave the same.

That's not what I meant. What I meant is that C++ .NET and C# are (or at least could) be used together in managed applications, and so their behavior should be at least similar to my mind.

While C++ can interact with managed languages via the managed extentions, that doesn't mean that all of it's features are available in the other managed languages. Indeed, they are fairly restrictive in the behaviors allowed in the others purely because they do NOT interop directly with unmanaged code.
Quote:

Quote:
As for your switch statement, what if the value isn't Yes or No?

OK, OK, that was a stupid example. I wanted to show the choice of some known values (or states, or anything), when we do handle all of the possible values.
Quote:
You do realize that you can cast an arbitrary integer to an enumeration

Yeah, C++ allows you to cope with lots of things that are logically wrong, like such casting to yes/no. Take the pointer juggling to get access to private members of a class for instance. That doesn't mean you must do each and every function so foolproof.
No, I mean in C#. Not just C++.
Quote:

Quote:
you either need to insert a default case that throws (the best idea) or just add an additional return statement.

Since the problem is probably logical, and you shouldn't go and cast random ints to enums around, it isn't necessary to throw, and the additional return statement is pointless, too (in this particular case)

Actually, the behavior is exceptional. There are many cases where you might want to cast an integer to an enumeration, but if the programmer makes a mistake, an exception will tell you. Something that silently ignoring it will not. Ignoring it can easily result in the bug showing up elsewhere, instead of much earlier and closer to the source. Hence you SHOULD throw.

Share this post


Link to post
Share on other sites
Tidbit:

The fact that not returning a value is only a warning (not an error) in C++, is because there used to be no "void" type in C. Thus "int" was used instead. It must remain a warning for compatability with old C code.

C#, not requiring backwards compatability with old, crap languages, does not have this problem.

Share this post


Link to post
Share on other sites
Quote:
Something that silently ignoring it will not. Ignoring it can easily result in the bug showing up elsewhere, instead of much earlier and closer to the source. Hence you SHOULD throw.

Being programmer error, an assert() may be more appropriate.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Ugh, don't use #pragma

Use the proper command line switches to treat all warnings as errors and write clean code (with cl.exe, /Wall /WX). Better yet, use gcc as a lint checker of your code. Gcc complains about 10x more stuff than Visual Studio in maximum warning mode (in my professional work, tons of things that are acceptable by vc++ are not acceptable by gcc, but if it was acceptable by gcc, vc++ was always still happy. This was with VC++ 7.1 and GCC 3.3.3).

If you must disable specific warnings, disable them on the invocation of your compiler (i.e. cl.exe can use /wd to disable a specific warning on the command line).

If you do it this way, you won't litter your source code with wierd build directives which are more often than not compiler specific.

Share this post


Link to post
Share on other sites
Quote:
Original post by Andrew Russell
Quote:
Something that silently ignoring it will not. Ignoring it can easily result in the bug showing up elsewhere, instead of much earlier and closer to the source. Hence you SHOULD throw.

Being programmer error, an assert() may be more appropriate.


I should have clarified, it may or may not be a programming error. For instance, data read from a configuration file or other source. You cannot guarantee that the data is valid, so you throw an exception instead.

Share this post


Link to post
Share on other sites
I too have gotten used to using 'treat warnings as errors" and I must say that I actually find it a very nice way of coding.

It is entirely possible to write code where logically all return paths to return a value, yet the compiler still gives a warning because it looks like it can get to the end where there is no return. This can never be solved fully because it's essentially the same thing as the halting problem.
Sheeva's example is not one of these cases though as has been already pointed out.

However in those cases I prefer to simply give in and keep the compiler happy.

Share this post


Link to post
Share on other sites
It bears mentioning that the standard specifies that a non-void function that completes without a return statement produces "undefined behavior", not "an undefined value". In other words, it might corrupt the stack, crash the program, crash the computer, or treat your dog with disrespect. So even if you expect to ignore the return value, it isn't a legitimate trick.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!