Der folgende Code generiert unterschiedliche Ergebnisse im Debugmodus und im Freigabemodus (mit 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;
}
Die Ausgabe des Debug-Modus, die wie erwartet ist:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255
Die Ausgabe des Freigabemodus, bei dem das i:15-Ergebnis nicht korrekt ist:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255
Durch Auswahl von „Optimierung -> Nicht zu optimieren“ in Visual Studio im Freigabemodus ist das Ausgabeergebnis korrekt. Ich würde jedoch gerne wissen, warum der Optimierungsprozess zu einer fehlerhaften Ausgabe führen könnte.
Aktualisieren:
Wie von Mohit JainBy vorgeschlagen, Drucke von:
printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;
Die Ausgabe des Freigabemodus ist korrekt:
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
Das ist interessant, zumindest aus historischer Perspektive. Ich kann das Problem mit VC 2008 (15.00.30729.01) reproduzieren und VC 2010 (16.00.40219.01) (für entweder 32-Bit x86 oder 64-Bit x64). Das Problem tritt bei keinem der Compiler auf, die ich ab VC 2012 (17.00.61030) ausprobiert habe.
Der Befehl, den ich zum Kompilieren verwendet habe: cl /Ox vc15-bug.cpp /FAsc
Da VC 2008 (und 2010) ziemlich alt ist und der Fix bereits seit mehreren Jahren vorhanden ist, können Sie meiner Meinung nach keine Aktion von Microsoft erwarten, außer einen neueren Compiler zu verwenden (obwohl vielleicht jemand eine Problemumgehung vorschlagen kann).
Das Problem ist, dass der Test bestimmt, ob der Wert erzwungen werden sollte 255
basiert auf der Anzahl der Schleifen und nicht auf dem tatsächlichen Ergebnis der i * 16
Ausdruck. Und der Compiler bekommt einfach die falsche Zählung, wann er anfangen sollte, den Wert zu erzwingen 255
. Ich habe keine Ahnung, warum das passiert – es ist nur der Effekt, den ich sehe:
; 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 : }
Aktualisieren: Alle Versionen von VC, die ich vor VC 2008 installiert habe, haben denselben Fehler, außer VC6 – das Kompilieren des Programms stürzt den VC6-Compiler ab:
vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
Dies ist also ein Fehler, der in MSVC in der einen oder anderen Form mehr als 10 Jahre andauerte!
Unter der Annahme, dass Ihre gemeldeten Fakten korrekt sind, wäre dies ein Compiler-Fehler. Überprüfen Sie die neueste Version des Compilers. Wenn der Fehler immer noch vorhanden ist, senden Sie einen Fehlerbericht.
Das sieht aus wie ein Compiler-Fehler (und ein ziemlich bedeutender noch dazu).
– WhozCraig
9. Juli 2015 um 5:49 Uhr
@WhozCraig Aktualisiert nur die Ausgabe von
i * 16
in der Post, und das Ergebnis ist korrekt.– Lorris Lin
9. Juli 2015 um 6:17 Uhr
@juanchopanza: Aus meiner Erfahrung mit MS und Bugfixes für VS beheben sie solche Fehler, nachdem sie darüber informiert wurden, wenden diese Fixes jedoch nicht auf ältere Versionen von VS an, wenn man also aus irgendeinem Grund gezwungen ist, eine ältere Version von zu verwenden VS, dann bleibt man bei solchen Bugs hängen, bis man auf eine neuere Version upgraden kann.
– Kaiserludi
9. Juli 2015 um 11:27 Uhr
FWIW funktioniert gut mit dem kommenden Visual Studio 2015
– ismail
9. Juli 2015 um 17:58 Uhr