Poniższy kod podaje inne dane wyjściowe podczas uruchamiania wydania w programie Visual Studio i uruchamiania wydania poza programem Visual Studio. Używam Visual Studio 2008 i celuję w .NET 3.5. Próbowałem także .NET 3.5 SP1.
Podczas uruchamiania poza Visual Studio, JIT powinien się uruchomić. Albo (a) dzieje się coś subtelnego z C #, którego mi brakuje lub (b) JIT jest w błędzie. Wątpię, czy JIT może się nie udać, ale brakuje mi innych możliwości ...
Dane wyjściowe podczas uruchamiania w programie Visual Studio:
0 0,
0 1,
1 0,
1 1,
Dane wyjściowe podczas uruchamiania wersji poza Visual Studio:
0 2,
0 2,
1 2,
1 2,
Jaki jest powód?
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();
}
}
}
Odpowiedzi:
Jest to błąd optymalizatora JIT. Rozwija wewnętrzną pętlę, ale nie aktualizuje poprawnie wartości oVec.y:
Błąd znika, gdy pozwalasz zwiększać oVec.y do 4, to zbyt wiele połączeń, aby rozwinąć.
Jednym z obejść tego jest:
AKTUALIZACJA: ponownie sprawdzona w sierpniu 2012 r., Ten błąd został naprawiony w wersji jitter 4.0.30319. Ale nadal jest obecny w jitter v2.0.50727. Wydaje się mało prawdopodobne, że naprawią to w starej wersji po tak długim czasie.
źródło
Wierzę, że jest to prawdziwy błąd kompilacji JIT. Zgłosiłbym to do Microsoft i sprawdził, co mówią. Co ciekawe, odkryłem, że JIT x64 nie ma tego samego problemu.
Oto moje czytanie JIT x86.
Wygląda na to, że optymalizacja mi się nie udała ...
źródło
Skopiowałem twój kod do nowej aplikacji konsoli.
Więc to JIT x86 niepoprawnie generuje kod. Usunąłem mój oryginalny tekst na temat zmiany kolejności pętli itp. Kilka innych odpowiedzi tutaj potwierdziło, że JIT nieprawidłowo odwija pętlę na x86.
Aby rozwiązać problem, możesz zmienić deklarację IntVec na klasę i działa ona we wszystkich smakach.
Pomyśl, że to musi iść na MS Connect ....
-1 do Microsoft!
źródło