Poniższy kod generuje różne wyniki w trybie debugowania i trybie wydania (przy użyciu programu Visual Studio 2008):
int _tmain(int argc, _TCHAR* argv[])
{
for( int i = 0; i < 17; i++ )
{
int result = i * 16;
if( result > 255 )
{
result = 255;
}
printf("i:%2d, result = %3d\n", i, result) ;
}
return 0;
}
Dane wyjściowe trybu debugowania, zgodnie z oczekiwaniami:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255
Wyjście trybu zwolnienia, gdzie wynik i: 15 jest nieprawidłowy:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255
Po wybraniu opcji „Optymalizacja -> Nie optymalizować” w programie Visual Studio w trybie wydania, wynik wyjściowy będzie poprawny. Chciałbym jednak wiedzieć, dlaczego proces optymalizacji może prowadzić do błędnych wyników.
Aktualizacja:
Jak sugeruje Mohit JainBy, drukuje:
printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;
Wyjście trybu zwolnienia jest poprawne:
i: 0, result = 0, i*16=0
i: 1, result = 16, i*16=16
(...)
i:14, result = 224, i*16=224
i:15, result = 240, i*16=240
i:16, result = 255, i*16=256
c++
c
optimization
visual-studio-2008
compiler-bug
Lorris Lin
źródło
źródło
i * 16
w poście, a wynik jest poprawny.Odpowiedzi:
To ciekawe, przynajmniej z historycznego punktu widzenia. Mogę odtworzyć problem z VC 2008 (15.00.30729.01) i VC 2010 (16.00.40219.01) (ukierunkowany na 32-bitowe x86 lub 64-bitowe x64). Problem nie występuje w przypadku żadnego z kompilatorów, które próbowałem, począwszy od VC 2012 (17.00.61030).
Polecenie, którego użyłem do skompilowania:
cl /Ox vc15-bug.cpp /FAsc
Ponieważ VC 2008 (i 2010) jest dość stary, a poprawka jest już dostępna od kilku lat, nie sądzę, aby można było oczekiwać od Microsoftu jakiejkolwiek akcji poza użyciem nowszego kompilatora (choć może ktoś może zasugerować obejście tego problemu).
Problem polega na tym, że test określający, czy wartość powinna zostać wymuszona,
255
jest wykonywany na podstawie liczby pętli, a nie faktycznego wynikui * 16
wyrażenia. A kompilator po prostu błędnie oblicza, kiedy powinien zacząć wymuszać wartość255
. Nie mam pojęcia, dlaczego tak się dzieje - to tylko efekt, który widzę:; 6 : for( int i = 0; i < 17; i++ ) 00001 33 f6 xor esi, esi $LL4@main: 00003 8b c6 mov eax, esi 00005 c1 e0 04 shl eax, 4 ; 7 : { ; 8 : int result = i * 16; ; 9 : ; 10 : if( result > 255 ) // the value `esi` is compared with in the following line should be 15! 00008 83 fe 0e cmp esi, 14 ; 0000000eH 0000b 7e 05 jle SHORT $LN1@main ; 11 : { ; 12 : result = 255; 0000d b8 ff 00 00 00 mov eax, 255 ; 000000ffH $LN1@main: ; 13 : }
Aktualizacja : Wszystkie wersje VC, które zainstalowałem wcześniej niż VC 2008 mają ten sam błąd, z wyjątkiem VC6 - kompilacja programu powoduje awarię kompilatora VC6:
vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
Więc to jest błąd, który trwał w MSVC w takiej czy innej formie przez ponad 10 lat!
źródło
result > 255
naresult >= 255
, zachowuje się poprawnie. W VS2010 to zmienia sięcmp esi, 14
nacmp esi, 16
(ijle
tojl
).Zakładając, że zgłoszone fakty są poprawne, byłby to błąd kompilatora. Sprawdź najnowszą wersję kompilatora. Jeśli błąd nadal występuje, prześlij raport o błędzie.
źródło