从C++ 11中的"switch"语句"返回"现在是错误的吗?

Rog*_*and 24 c++ c++11 visual-studio-2012

使用VS2012,我注意到一个switch已经工作了好几年的东西现在似乎在发布版本中被打破了,但在Debug版本中正常工作(或至少像以前一样).我无法看到代码的任何错误,所以我们会感谢一些关于returnswitch块中使用语句的正确性的反馈.

以下代码编译好,但在Win7 32位的Release版本中提供了错误的输出...

#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;
}
Run Code Online (Sandbox Code Playgroud)

如果您可以重复此问题,并拥有MS Connect登录,也许您也可以在这里投票?

实际结果

发布版本会产生以下错误结果:

GetFloat() - entered
GetFloat() - case 3 entered
fValue = 0.000000
Run Code Online (Sandbox Code Playgroud)

预期成绩

Debug构建提供以下正确结果:

GetFloat() - entered
GetFloat() - case 3 entered
fValue = 3.000000
Run Code Online (Sandbox Code Playgroud)

MS Connect错误报告

jco*_*der 7

听起来这可能是这个错误?返回以类似方式生成的浮点值存在问题?


exa*_*ple 6

绝对是一个编译器错误.这是正在执行的精简asm代码(跳转等).编译器会删除一些它认为不必要的代码 - 即使它不是.


发布版本:

// 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
Run Code Online (Sandbox Code Playgroud)

调试版本:

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
Run Code Online (Sandbox Code Playgroud)


Bar*_*icz 5

从所有结果中收集数据,很可能是编译器错误.

  • x64正常工作
  • /O1 工作正常
  • 好吧,Debug工作正常
  • 它给出了同样的错误类型上都coutprintf

并且,可能是最重要的 - 它符合100%标准.所以它应该工作.

  • 从现在开始,我不会用10英尺长的棍子接触VS编译器. (9认同)
  • 不过,这是一个*可怕的*错误. (3认同)