Using VS2012, I noticed that a switch
that's been working for several years now seems to be broken in Release builds but works correctly (or at least as it used to) in Debug builds. I can't see anything at all wrong with the code so would appreciate some feedback on the correctness of using return
statements from within a switch
block.
The following code compiles ok but gives the wrong output in a Release build on Win7 32-bit...
#include <stdio.h> #include <tchar.h> class CSomeClass { public: float GetFloat(int nInt) { printf("GetFloat() - entered\n"); switch (nInt) { case 1 : printf("GetFloat() - case 1 entered\n"); return 0.5F; case 0 : printf("GetFloat() - case 0 entered\n"); return 1.0F; case 2 : printf("GetFloat() - case 2 entered\n"); return 2.0F; case 3 : printf("GetFloat() - case 3 entered\n"); return 3.0F; case 4 : printf("GetFloat() - case 4 entered\n"); return 4.0F; } printf("GetFloat() - exit\n"); return 1.0F; } }; int _tmain(int argc, _TCHAR* argv[]) { CSomeClass pClass; float fValue = pClass.GetFloat(3); printf("fValue = %f\n", fValue); return 0; }
If you can repeat the problem, and have a MS Connect login, maybe you can vote it up here too?
Actual results
Release build gives the following incorrect result:
GetFloat() - entered GetFloat() - case 3 entered fValue = 0.000000
Expected results
Debug build gives the following correct result:
GetFloat() - entered GetFloat() - case 3 entered fValue = 3.000000
MS Connect bug report
The JavaScript switch statement can contain return statements if it is present inside a function. The function will return the value in the switch statement and the code after the switch statement will not be executed.
If two cases in a 'switch' statement are identical, the second case will never be executed. This most likely indicates a copy-paste error where the first case was copied and then not properly adjusted.
The value of the expressions in a switch-case statement must be an ordinal type i.e. integer, char, short, long, etc. Float and double are not allowed. The case statements and the default statement can occur in any order in the switch statement.
It sounds like it might be this bug? Where there is a problem in returning floating point values generated in a similar way?
Definitely a compiler error. Here is the stripped down asm code being executed (jumps etc. removed). The compiler removes some code it assumes to be unnecessary - even though it is not.
Release build:
// inside GetFloat 00E0104D fld dword ptr ds:[0E021D8h] // load constant float onto FPU stack 00E01068 add esp,4 00E0106B ret // back in main 00E01098 cvtss2sd xmm0,xmm0 // convert float to double. assumes the returned value to be in xmm0 00E0109C sub esp,8 00E0109F movsd mmword ptr [esp],xmm0 // push double being printed (xmm0 is with high likelyhood = 0) 00E010A4 push 0E021B8h // push output string 00E010A9 call dword ptr ds:[0E02090h] // call printf
Debug build:
003314B0 fld dword ptr ds:[335964h] // load const float onto FPU stack [...] 00331500 mov esp,ebp 00331502 pop ebp 00331503 ret 4 // back in main 00331598 fstp dword ptr [fValue] // copies topmost element of the FPU stack to [fValue] 0033159B cvtss2sd xmm0,dword ptr [fValue] // correctly takes returned value (now inside [fValue] for conversion to double 003315A0 mov esi,esp 003315A2 sub esp,8 003315A5 movsd mmword ptr [esp],xmm0 // push double being printed 003315AA push 335940h // push output string 003315AF call dword ptr ds:[3392C8h] // call printf
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With