MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 19:04
Оценка: -2
Не могу не поделиться.

Как Вы думаете, что выведет в stdout следующий код в случае MSVC-11.0?

#include <cstdio>
#include <iostream>

class Foo
{
public:
    float getFloat(int value)
    {
        switch (value)
        {
        case 1:
            std::printf("1 \n");
            return 0.5F;
        case 0:
            std::printf("0 \n");
            return 1.0F;
        case 2:
            std::printf("2 \n");
            return 2.0F;
        case 3:
            std::printf("3 \n");
            return 3.0F;
        case 4:
            std::printf("4 \n");
            return 4.0F;
        }
        return 1.0F;
    }
};

int main()
{
    Foo instance;
    std::cout << instance.getFloat(3) << '\n';
}
Re: MSVC-11.0 - вопрос
От: dilmah США  
Дата: 14.02.13 19:17
Оценка: -1
NT>Как Вы думаете, что выведет в stdout следующий код в случае MSVC-11.0?

почему это должно быть интересно?
есть sync_with_stdio чтобы это работало правильно.
Re[2]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 19:42
Оценка: -2
D>почему это должно быть интересно?
D>есть sync_with_stdio чтобы это работало правильно.

А если ещё подумать? Неужели я бы стал спрашивать Вас о таком?
Re[3]: MSVC-11.0 - вопрос
От: dilmah США  
Дата: 14.02.13 19:50
Оценка:
ну не томи, не у всех же есть MSVC
Re[4]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 19:51
Оценка: -2
D>ну не томи, не у всех же есть MSVC

Пусть остальные посмотрят, не хочу рассказывать раньше времени.
Re[5]: MSVC-11.0 - вопрос
От: Alca Украина  
Дата: 14.02.13 20:02
Оценка: -1
Здравствуйте, Nikita.Trophimov, Вы писали:

D>>ну не томи, не у всех же есть MSVC


NT>Пусть остальные посмотрят, не хочу рассказывать раньше времени.


Ты, что троль??

ВЫвод: 3 3
Re: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:07
Оценка: 7 (1) -1
Раз уж понеслись минусы без пояснений (молодцы, однако), то привожу ответ:

Debug

3
3


Release

3
0

Re: MSVC-11.0 - вопрос
От: uzhas Ниоткуда  
Дата: 14.02.13 20:07
Оценка: :)
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Не могу не поделиться.

все же смог
Re[2]: MSVC-11.0 - вопрос
От: Piko  
Дата: 14.02.13 20:11
Оценка: 1 (1) +1
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Раз уж понеслись минусы без пояснений (молодцы, однако)


А тебя какая разница? Минусы, плюсы?
Ты вообще <b>НИ ОДНОЙ</b> оценки никому не поставил.
Re[3]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:13
Оценка:
Сказать не легче?
Re[4]: MSVC-11.0 - вопрос
От: Piko  
Дата: 14.02.13 20:14
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Сказать не легче?


Что? Кому?
Re: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:17
Оценка: 64 (6)
https://connect.microsoft.com/VisualStudio/feedback/details/779043/c-switch-statement-broken-in-release-build#details
Re[5]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:18
Оценка:
P>Что? Кому?

Вы как в дет. саде... Мне. То, что не нравится / с чем не согласны.
Re: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:19
Оценка: 32 (1)
Ссылка на StackOverflow:

http://stackoverflow.com/questions/14835262/is-it-now-wrong-to-return-from-a-switch-statement-in-c11
Re[2]: MSVC-11.0 - вопрос
От: Piko  
Дата: 14.02.13 20:20
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>https://connect.microsoft.com/VisualStudio/feedback/details/779043/c-switch-statement-broken-in-release-build#details


там по ссылке:
#include <stdio.h>
#include <tchar.h>

float GetFloat(int nInt)
    {
        printf("%s", "GetFloat() - entered\n");
        switch (nInt)
        {
        case 1 :
            printf("%s", "GetFloat() - case 1 entered\n");
            return 0.5F;
        case 0 :
            printf("%s", "GetFloat() - case 0 entered\n");
            return 1.0F;
        case 2 :
            printf("%s", "GetFloat() - case 2 entered\n");
            return 2.0F;
        case 3 :
            printf("%s", "GetFloat() - case 3 entered\n");
            return 3.0F;
        case 4 :
            printf("%s", "GetFloat() - case 4 entered\n");
            return 4.0F;
        }
        printf("%s", "GetFloat() - exit\n");
        return 1.0F;
    }



int _tmain(int argc, _TCHAR* argv[])
{
    printf("fValue = %2.2f\n", GetFloat(3));

    return 0;
}


Теперь ясно откуда эти "getFloat" растут.
Почему бы сразу было не сказать в чём дело?
Re[3]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 20:22
Оценка:
P>Теперь ясно откуда эти "getFloat" растут.

Ну да, я ничего себе не присваиваю. Ссылки приведены.

P>Почему бы сразу было не сказать в чём дело?


Очевидно же — чтобы подогреть интерес к обсуждаемой теме. Вам, как я вижу, это наоборот не понравилось, так что извиняюсь.
Re[2]: MSVC-11.0 - вопрос
От: rusted Беларусь  
Дата: 14.02.13 20:49
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Ссылка на StackOverflow:


NT>http://stackoverflow.com/questions/14835262/is-it-now-wrong-to-return-from-a-switch-statement-in-c11


Посмотрел asm вывод: баг есть только при /arch:SSE2, getFloat возвращает результат в FPU, а main получается вот таким:

; 27   : {

    mov    ecx, 3
    call    ?getFloat@@YAMH@Z            ; getFloat

; 28   :     printf( "%f\n", getFloat( 3 ) );

    cvtss2sd xmm0, xmm0
    sub    esp, 8
    movsd    QWORD PTR [esp], xmm0
    push    OFFSET ??_C@_03PPOCCAPH@?$CFf?6?$AA@
    call    _printf
    add    esp, 12                    ; 0000000cH

; 29   : }


т.е. ожидает результат getFloat в xmm0.

Если компилить с /arch:SSE, то всё нормально:

; 27   : {

    push    ebp
    mov    ebp, esp
    push    ecx
    mov    ecx, 3
    call    ?getFloat@@YAMH@Z            ; getFloat
    fstp    DWORD PTR $T1[ebp]

; 28   :     printf( "%f\n", getFloat( 3 ) );

    fld    DWORD PTR $T1[ebp]
    sub    esp, 8
    fstp    QWORD PTR [esp]
    push    OFFSET ??_C@_03PPOCCAPH@?$CFf?6?$AA@
    call    _printf
    add    esp, 12                    ; 0000000cH

; 29   : }
Re[2]: MSVC-11.0 - вопрос
От: Шахтер Интернет  
Дата: 14.02.13 20:52
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>https://connect.microsoft.com/VisualStudio/feedback/details/779043/c-switch-statement-broken-in-release-build#details


Я глянул ассемблерный листинг.
Сама функция getFloat() сгенерирована правильно. Но вот дальше что-то странное.

    mov    ecx, 3
    call    ?getFloat@Foo@@QAEMH@Z            ; Foo::getFloat

; 35   :     Foo instance;
; 36   :     std::cout << instance.getFloat(3) << '\n';

    push    ecx
    mov    ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
    movss    DWORD PTR [esp], xmm0
    call    DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
    mov    ecx, eax
    call    ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z ; std::operator<<<std::char_traits<char> >


Короче, похоже, нарушены соглашения по вызовам.

getFloat() грузит результат на вершину FP стека, а вызывающая функция забирает результат из xmm0.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 21:02
Оценка:
Более того, судя по StackOverflow, результат также будет зависить от уровня оптимизации и 64-битного режима.
Re[3]: MSVC-11.0 - вопрос
От: Nikita.Trophimov  
Дата: 14.02.13 21:03
Оценка:
Ш>Я глянул ассемблерный листинг.
Ш>Сама функция getFloat() сгенерирована правильно. Но вот дальше что-то странное.

Да, на StackOverflow уже обсуждали асм листинг. Блин, этот баг действительно тяжело ловить...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.