以下代码在调试模式和发布模式下(使用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;
}
调试模式的输出,如预期的那样:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255
释放模式的输出,其中i:15结果不正确:
i: 0, result = 0
i: 1, result = 16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255
通过在发布模式下的Visual Studio中选择“优化->不优化”,输出结果将是正确的。但是我想知道为什么优化过程可能导致错误的输出。
更新:
正如Mohit JainBy所建议的那样,打印:
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
至少从历史角度来看,这很有趣。我可以重现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)的版本相当老,并且修复程序已经存在了几年,所以我认为除了使用较新的编译器之外,您不会期望Microsoft采取任何措施(尽管也许有人会建议解决方法)。
问题在于,255
根据循环计数而不是i * 16
表达式的实际结果来完成确定是否应强制使用该值的测试。并且编译器只是在应该开始将值强制为时弄错了计数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 2008的VC都有相同的错误,但VC6除外-编译程序会使VC6编译器崩溃:
vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
因此,这是一种以一种或多种形式存在于MSVC中的错误,已经存在了10多年!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句