En mode release, 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 de publication (à l’aide de Visual Studio 2008):

int _tmain(int argc, _TCHAR* argv[]) { for( int i = 0; i  255 ) { result = 255; } printf("i:%2d, result = %3d\n", i, result) ; } return 0; } 

La sortie du mode de 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ù i: 15 résultat 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 de publication, le résultat de la sortie sera correct. Cependant, je voudrais savoir pourquoi le processus d’optimisation pourrait conduire à des résultats erronés.


Mettre à jour:

Comme suggéré par Mohit JainBy, estampes 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 

C’est intéressant, du moins dans une perspective historique. Je peux reproduire le problème avec VC 2008 (15.00.30729.01) et VC 2010 (16.00.40219.01) (ciblant soit 32 bits x86 ou 64 bits x64). Le problème ne se produit avec aucun des compilateurs que j’ai essayé à partir de VC 2012 (17.00.61030).

La commande utilisée pour comstackr: cl /Ox vc15-bug.cpp /FAsc

Puisque VC 2008 (et 2010) est assez 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, sauf pour utiliser un compilateur plus récent.

Le problème est que le test pour déterminer si la valeur doit être forcée à 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 compte faux 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 avant VC 2008 ont le même bogue, sauf VC6 – la compilation du programme bloque le compilateur VC6:

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

C’est donc un bug qui a duré plus de 10 ans sous MSVC sous une forme ou une autre!

En supposant que vos faits rapportés sont corrects, ce serait un bogue de compilation. Vérifiez la dernière version du compilateur. Si le bogue est toujours présent, soumettez un rapport de bogue.