大佬教程收集整理的这篇文章主要介绍了visual-c – 用循环优化VC 2015除以零,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我们刚刚从VC 2008开始将我们的开发环境转换为VC 2015.在此之后我们发现了问题:尽管在C代码中测试了分隔符,程序仍然将0除以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编译并使用默认的Release选项,在运行时它将除以零.由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.显然,只需通过编译器作业即可正确地修复它.
我玩了几个编译器选项,比如-d2SSAOptimizer-和-Oxx,但解决这个问题的唯一选择是-Od.
问题:
>这是一个错误吗?自VC 2008以来,C标准发生了很大变化,所以可能会受到这样的影响吗?
>主要问题是,除了-Ob之外,是否有通过编译器选项解决问题的解决方法?
这确实是编译器本身的一个错误,特别是“Invariant Code Motion”优化过程中的安全检查.我已经解决了这个问题,它应该出现在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除以零全部内容,希望文章能够帮你解决visual-c – 用循环优化VC 2015除以零所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。