在发布模式下,代码行为不像预期的那样

以下代码在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 * 16expression式的实际结果。 而编译器只是简单地得到错误的计数,当它应该开始迫使值为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多年的错误!

假设你所报告的事实是正确的,这将是一个编译器错误。 检查编译器的最新版本。 如果错误仍然存​​在,请提交错误报告。