web-dev-qa-db-fra.com

En mode de publication, le comportement du code n’est pas celui attendu

Le code suivant génère des résultats différents en mode débogage et en mode édition (à l'aide de 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;
}

La sortie du mode débogage, qui est comme prévu:

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

La sortie du mode de libération, où le résultat i: 15 n’est pas correct:

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

En choisissant "Optimisation -> Ne pas optimiser" dans Visual Studio en mode édition, le résultat de la sortie sera correct. Cependant, j'aimerais savoir pourquoi le processus d'optimisation pourrait conduire à une sortie erronée.


Mise à jour:

Comme suggéré par Mohit JainBy, imprime par:

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

La sortie du mode de libération est correcte:

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

C'est intéressant, du moins d'un point de vue historique. Je peux reproduire le problème avec VC 2008 (15.00.30729.01) et VC 2010 ( 16.00.40219.01) (ciblant soit x86 32 bits ou x64 64 bits). Le problème ne se produit pas avec les compilateurs que j'ai essayés en commençant par VC 2012 (17.00.61030).

La commande que j'avais l'habitude de compiler: cl /Ox vc15-bug.cpp /FAsc

Comme VC 2008 (et 2010) est plutôt ancien et que le correctif existe depuis plusieurs années, je ne pense pas que vous puissiez vous attendre à une action de la part de Microsoft si ce n'est d'utiliser un compilateur plus récent (bien que quelqu'un puisse peut-être suggérer une solution de contournement).

Le problème est que le test pour déterminer si la valeur doit être forcée sur 255 Est effectué en fonction du nombre de boucles plutôt que du résultat réel de l'expression i * 16. Et le compilateur obtient simplement le nombre incorrect pour le moment où il devrait commencer à forcer la valeur à 255. Je ne sais pas pourquoi cela se produit - c'est juste l'effet que je vois:

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

Mise à jour: Toutes les versions de VC que j'ai installées plus tôt que VC 2008 ont le même bogue, sauf que VC6 - la compilation du programme bloque le compilateur VC6:

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

Il s’agit donc d’un bogue qui a duré plus de 10 ans sous MSVC sous une forme ou une autre!

115
Michael Burr

En supposant que les faits rapportés soient corrects, il s'agirait d'un bogue du compilateur. Vérifiez la dernière version du compilateur. Si le bogue est toujours présent, soumettez un rapport de bogue.

16
David Heffernan