在发布模式下,代码行为不像预期的那样
以下代码在debugging模式和发行模式(使用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; }
debugging模式的输出如预期的那样:
i: 0, result = 0 i: 1, result = 16 (...) i:14, result = 224 i:15, result = 240 i:16, result = 255
释放模式的输出,其中我:15结果是不正确的:
i: 0, result = 0 i: 1, result = 16 (...) i:14, result = 224 i:15, result = 255 i:16, result = 255
在释放模式下,通过在Visual Studio中select“优化 – >不优化”,输出结果将是正确的。 不过,我想知道为什么优化过程可能导致错误的输出。
更新:
正如Mohit JainBy所build议的那样:
printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;
释放模式输出是正确的:
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
至less从历史的angular度来看,这很有趣。 我可以重现VC 2008(15.00.30729.01) 和 VC 2010(16.00.40219.01)(针对32位x86或64位x64)的问题。 我从VC 2012(17.00.61030)开始试过的任何编译器都不会出现这个问题。
我用来编译的命令: cl /Ox vc15-bug.cpp /FAsc
由于VC 2008(和2010)相当老,修复已经好几年了,我认为除了使用更新的编译器(尽pipe也许有人可以提出一种解决方法),我不认为你可以期待微软的任何行动。
问题是确定值是否应该强制为255
是基于循环计数而不是i * 16
expression式的实际结果。 而编译器只是简单地得到错误的计数,当它应该开始迫使值为255
。 我不知道为什么会发生这种情况 – 这只是我看到的效果:
; 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 : }
更新 :所有版本的VC我安装早于VC 2008有相同的错误,除了VC6 – 编译程序崩溃VC6编译器:
vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
所以这是一个在MSVC中以一种或另一种forms持续了10多年的错误!
假设你所报告的事实是正确的,这将是一个编译器错误。 检查编译器的最新版本。 如果错误仍然存在,请提交错误报告。