webentwicklung-frage-antwort-db.com.de

Im Freigabemodus ist das Codeverhalten nicht wie erwartet

Der folgende Code generiert unterschiedliche Ergebnisse im Debug- und Release-Modus (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, wie erwartet:

i: 0, result =   0
i: 1, result =  16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255

Die Ausgabe des Freigabemodus, in dem das Ergebnis i: 15 nicht korrekt ist:

i: 0, result =   0
i: 1, result =  16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255

Wenn Sie in Visual Studio im Release-Modus "Optimierung -> Nicht optimieren" auswählen, ist das Ausgabeergebnis korrekt. Ich möchte jedoch wissen, warum der Optimierungsprozess zu einer fehlerhaften Ausgabe führen kann.


pdate:

Wie von Mohit JainBy vorgeschlagen, druckt von:

printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;

Die Ausgabe im 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
131
Lorris Lin

Das ist zumindest aus historischer Sicht interessant. Ich kann das Problem mit VC 2008 (15.00.30729.01) und VC 2010 (reproduzieren. 16.00.40219.01) (für 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, mit dem ich kompiliert habe: cl /Ox vc15-bug.cpp /FAsc

Da VC 2008 (und 2010) ziemlich alt ist und die Fehlerbehebung bereits seit einigen Jahren besteht, können Sie von Microsoft meines Erachtens keine andere Aktion erwarten, als einen neueren Compiler zu verwenden (obwohl vielleicht jemand einen vorschlagen kann) Problemumgehung).

Das Problem ist, dass der Test, um zu bestimmen, ob der Wert auf 255 Gesetzt werden soll, auf der Grundlage der Schleifenzahl und nicht des tatsächlichen Ergebnisses des Ausdrucks i * 16 Durchgeführt wird. Und der Compiler erhält einfach die falsche Zählung, wenn er den Wert auf 255 Zwingen soll. 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
[email protected]:
  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 [email protected]

; 11   :        {
; 12   :            result = 255;

  0000d b8 ff 00 00 00   mov     eax, 255       ; 000000ffH
[email protected]:

; 13   :        }

pdate: Alle Versionen von VC, die ich vor VC 2008 installiert habe, haben denselben Fehler, außer VC6 - beim Kompilieren des Programms stürzt der VC6-Compiler ab:

vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR

Das ist also ein Fehler, der in der einen oder anderen Form mehr als 10 Jahre in MSVC andauerte!

115
Michael Burr

Vorausgesetzt, Ihre gemeldeten Fakten sind korrekt, wäre dies ein Compiler-Fehler. Überprüfen Sie die neueste Version des Compilers. Wenn der Fehler immer noch vorhanden ist, reichen Sie einen Fehlerbericht ein.

16
David Heffernan