64位-在没有调试的情况下启动的C#64位版本构建与在启动调试(BigInteger)时的行为不同
本文关键字:调试 启动 BigInteger 情况下 C#64 版本 64位 构建 | 更新日期: 2023-09-27 18:00:38
我是C#的新手,遇到了以下代码的问题(我的目标框架是4.5,我添加了对System.Numerics的引用):
using System;
using System.Numerics;
namespace Test
{
class Program
{
static BigInteger Gcd(BigInteger x, BigInteger y)
{
Console.WriteLine("GCD {0}, {1}", x, y);
if (x < y) return Gcd(y, x);
if (x % y == 0) return y;
return Gcd(y, x % y);
}
static void Main(string[] args)
{
BigInteger a = 13394673;
BigInteger b = 53578691;
Gcd(a, b);
}
}
}
当版本构建开始调试时(VisualStudio中的F5,以及程序末尾的一个断点,这样我就可以看到输出),我得到以下输出:
GCD 13394673, 53578691
GCD 53578691, 13394673
GCD 13394673, 13394672
GCD 13394672, 1
然而,当版本构建在没有调试的情况下启动时(Ctrl-F5),我会得到以下内容:
GCD 13394673, 53578691
GCD 53578691, 53578691
奇怪的是,如果我添加一个控制台。ReadLine()在程序结束时,它按预期工作!
你知道是什么原因造成的吗?谢谢
这是中的x64抖动优化器错误。NET 4.0至4.5.2。描述它相当困难,由于BigInteger的使用,代码生成相当重。x64抖动有struct类型(如BigInteger)的优化器错误历史,因此这可能是根本原因。在这种方法中,与可能的尾部调用优化相结合是最有可能的触发因素。
我通常会建议报告这样的错误,但这种抖动的日子已经不多了。微软决定将其退役并彻底重写。中提供。NET 4.6-VS2015,项目代码名称为RyuJIT。它没有这个bug。
几种可能的解决方案:
Project+Properties,Build选项卡,Platform target=x86。这迫使程序在32位模式下运行,并使用x86抖动,它没有这个错误。
或者使用属性禁用此方法的优化:
using System.Runtime.CompilerServices;
...
[MethodImpl(MethodImplOptions.NoOptimization)]
static BigInteger Gcd(BigInteger x, BigInteger y) {
// etc...
}
还好,繁重的工作在BigInteger类中,所以禁用优化不会影响执行时间。