Подтвердить что ты не робот

Неправильно ли "возвращаться" из инструкции "switch" в С++ 11?

Используя VS2012, я заметил, что switch, работающий уже несколько лет, кажется, сломан в сборках Release, но работает корректно (или, по крайней мере, так, как было) в сборке Debug. Я не вижу ничего плохого в коде, поэтому я бы по достоинству оценил правильность использования инструкций return из блока switch.

Следующий код компилируется нормально, но дает неправильный вывод в сборке Release на 32-битном Win7...

#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;
}

Если вы можете повторить проблему и иметь учетную запись MS Connect, возможно, вы тоже можете проголосовать за нее?

Фактические результаты

Релиз сборки дает следующий неверный результат:

GetFloat() - entered
GetFloat() - case 3 entered
fValue = 0.000000

Ожидаемые результаты

Сборка отладки дает следующий правильный результат:

GetFloat() - entered
GetFloat() - case 3 entered
fValue = 3.000000

Отчет об ошибке MS Connect

4b9b3361

Ответ 1

Кажется, это может быть эта ошибка? Где возникает проблема при возврате значений с плавающей запятой, сгенерированных аналогичным образом?

Ответ 2

Определенно ошибка компилятора. Здесь выполняется снятый код 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

Отладка сборки:

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

Ответ 3

Сбор данных из всех результатов, скорее всего, это ошибка компилятора.

  • x64 работает правильно
  • /O1 работает правильно
  • хорошо, Debug работает правильно
  • он дает такую ​​же ошибку как для cout, так и printf

И, наверное, самое главное - это 100% стандартов. Поэтому он должен работать.