En el modo release, el comportamiento del código no es el esperado
El siguiente código genera diferentes resultados en modo debug y modo release (usando 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 salida del modo de depuración, que es como se espera:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255
La salida del modo release, donde el resultado i: 15 no es correcto:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255
Al elegir "Optimización -> No optimizar" en Visual Studio en modo release, el resultado de salida será correcto. Sin embargo, me gustaría saber por qué el proceso de optimización podría conducir a errores salida.
Actualización:
Como sugiere Mohit JainBy, impresiones de:
printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;
La salida del modo de liberación es correcta:
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
2 answers
Esto es interesante, al menos desde una perspectiva histórica. Puedo reproducir el problema con VC 2008 (15.00.30729.01) y VC 2010 (16.00.40219.01) (focalización de 32-bit x86 o x64 de 64 bits). El problema no ocurre con ninguno de los compiladores que he probado a partir de VC 2012 (17.00.61030).
El comando que utilicé para compilar: cl /Ox vc15-bug.cpp /FAsc
Desde VC 2008 (y 2010) es bastante viejo y la solución ha estado en varios años, no creo que pueda espere cualquier acción de Microsoft excepto usar un compilador más nuevo (aunque tal vez alguien pueda sugerir una solución).
El problema es que la prueba para determinar si el valor debe ser forzado a 255
se realiza en función del recuento de bucles en lugar del resultado real de la expresión i * 16
. Y el compilador simplemente obtiene el conteo incorrecto para cuando debería comenzar a forzar el valor a 255
. No tengo idea de por qué sucede eso - es solo el efecto que veo:
; 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 : }
Actualización : Todas las versiones de VC que he instalado antes de VC 2008 tienen el mismo error, excepto VC6-compiling el programa se bloquea el compilador VC6:
vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
Así que este es un error que duró en MSVC de una forma u otra por más de 10 años!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-09 07:28:28
Asumiendo que los hechos reportados son correctos, esto sería un error del compilador. Compruebe la última versión del compilador. Si el error sigue presente, envíe un informe de error.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-09 08:51:08