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
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!
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.