gpt4 book ai didi

visual-c++ - 用循环优化除以零 VC++ 2015

转载 作者:行者123 更新时间:2023-12-04 21:32:42 25 4
gpt4 key购买 nike

史前:

我们刚刚将我们的开发环境从 VC++ 2008 切换到 VC++ 2015。之后我们发现了问题:尽管在 C++ 代码中测试了除法器,但程序仍将除法提高到 0。

测试代码:

#include <cstdlib>

int test(int n, int test_for_zero)
{
int result = 0;
for (int i = 0; i < n; ++i) {

if (test_for_zero)
result += rand() >> ((8 % test_for_zero) * test_for_zero);
}

return result;
}

int main()
{
return test(rand(), rand() & 0x80000000);
}

由 VC++ 2015 Update 3 或 VC++ 2017 编译,默认发布选项,运行时除以零。由 VC 2008 编译运行得很好。

分析:
; 6    :    for (int i = 0; i < n; ++i) {

test edi, edi
jle SHORT $LN15@main

; 7 :
; 8 : if (test_for_zero)
; 9 : result += rand() >> ((8 % test_for_zero) * test_for_zero);

mov ecx, DWORD PTR _test_for_zero$1$[ebp]
mov eax, 8
cdq
idiv ecx ; <== IT'S HERE, IDIV BEFORE CHECKING FOR ZERO
mov eax, edx
imul eax, ecx
mov DWORD PTR tv147[ebp], eax
test ecx, ecx
je SHORT $LN15@main
$LL11@main:
call ebx
mov ecx, DWORD PTR tv147[ebp]
sar eax, cl
add esi, eax
sub edi, 1
jne SHORT $LL11@main

编译器采用常量部分 ((8 % test_for_zero) * test_for_zero)循环体外,只是忘记进行测试 test_for_zero split 前。显然,只需正确地执行编译器工作,就可以轻松地将其固定到位。

我玩过几个编译器选项,比如 -d2SSAOptimizer--Oxx ,但解决此问题的唯一选择是 -Od .

问题:
  • 它是一个错误还是不是?自 VC 2008 以来,C++ 标准发生了重大变化,所以它会受到这样的影响吗?
  • 主要问题是,除了 -Ob 之外,是否有任何解决方法可以通过编译器选项解决问题?
  • 最佳答案

    感谢您的报告和小型重现(尤其是来自 Visual Studio 的反馈!),它们对隔离问题非常有帮助。

    这确实是编译器本身的一个错误,特别是“不变代码运动”优化过程中的安全检查。我已经解决了这个问题,它应该出现在 VS 15.7 中。

    目前,最简单的解决方法是通过 https://docs.microsoft.com/en-us/cpp/preprocessor/optimize 禁用具有此代码模式的函数的优化。 :

        #pragma optimize( "", off )  
    <Function containing code with this loop>
    #pragma optimize( "", on )

    不幸的是,此优化过程直接与优化器相关联,因此除了完全禁用优化器 (-Od) 之外,没有其他编译器选项可以解决您所发现的问题。

    关于visual-c++ - 用循环优化除以零 VC++ 2015,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47268824/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com