在Visual Studio中运行发行版并在Visual Studio外部运行发行版时,以下代码提供了不同的输出 . 我正在使用Visual Studio 2008并以.NET 3.5为目标 . 我也尝试过.NET 3.5 SP1 .
当在Visual Studio外部运行时,JIT应该启动 . 或者(a)C#中有一些微妙的东西我缺少或者(b)JIT实际上是错误的 . 我怀疑JIT可能出错,但我已经没有其他可能性......
在Visual Studio中运行时的输出:
0 0,
0 1,
1 0,
1 1,
在Visual Studio外部运行发布时的输出:
0 2,
0 2,
1 2,
1 2,
是什么原因?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
struct IntVec
{
public int x;
public int y;
}
interface IDoSomething
{
void Do(IntVec o);
}
class DoSomething : IDoSomething
{
public void Do(IntVec o)
{
Console.WriteLine(o.x.ToString() + " " + o.y.ToString()+",");
}
}
class Program
{
static void Test(IDoSomething oDoesSomething)
{
IntVec oVec = new IntVec();
for (oVec.x = 0; oVec.x < 2; oVec.x++)
{
for (oVec.y = 0; oVec.y < 2; oVec.y++)
{
oDoesSomething.Do(oVec);
}
}
}
static void Main(string[] args)
{
Test(new DoSomething());
Console.ReadLine();
}
}
}
3 回答
这是一个JIT优化器错误 . 它正在展开内部循环,但没有正确更新oVec.y值:
当你让oVec.y增加到4时,这个bug就会消失,那就是要打开的次数太多了 .
一个解决方法是:
更新:2012年8月重新检查,此错误已在版本4.0.30319抖动中修复 . 但仍然存在于v2.0.50727抖动中 . 在这么久之后,他们似乎不太可能在旧版本中解决这个问题 .
我相信这是一个真正的JIT编译错误 . 我会向微软报告,看看他们说了什么 . 有趣的是,我发现x64 JIT没有同样的问题 .
这是我对x86 JIT的阅读 .
这看起来像是对我不利的优化......
我将您的代码复制到新的控制台应用程序中 .
Debug Build
使用调试器和无调试器更正输出
切换到发布版本
再次,正确输出两次
创建了一个新的x86配置(I 'm on running X64 Windows 2008 and was using '任何CPU')
Debug Build
F5和CTRL F5输出正确
发布版本
附加调试器的正确输出
没有调试器 - Got the incorrect output
所以它是x86 JIT错误地生成代码 . 删除了我关于循环重新排序的原始文本等 . 这里的一些其他答案已经确认JIT在x86上不正确地展开循环 .
要解决此问题,您可以将IntVec的声明更改为类,并且它适用于所有类型 .
认为这需要继续MS Connect ....
-1到微软!