首页 文章

在发布模式下,代码行为不符合预期

提问于
浏览
131

以下代码在调试模式和发布模式下生成不同的结果(使用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中选择“优化 - >不优化”,输出结果将是正确的 . 但是,我想知道为什么优化过程可能导致错误的输出 .


Update:

正如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

2 回答

  • 115

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

  • 16

    这很有趣,至少从历史的角度来看 . 我可以使用VC 2008(15.00.30729.01) and VC 2010(16.00.40219.01)重现问题(针对32位x86或64位x64) . 我尝试从VC 2012(17.00.61030)开始尝试的任何编译器都不会出现此问题 .

    我用来编译的命令: cl /Ox vc15-bug.cpp /FAsc

    由于VC 2008(和2010)相当陈旧并且修复已经存在了好几年了,我认为除了使用更新的编译器之外你不会期待微软采取任何行动(尽管可能有人可以提出解决方法) .

    问题是确定值是否应该强制为 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   :        }
    

    Update :我在VC 2008之前安装的所有VC版本都有相同的bug,除了VC6 - 编译程序会导致VC6编译器崩溃:

    vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR
    

    所以这是一个在MSVC中以这种或那种形式持续超过10年的错误!

相关问题