Kode berikut memberikan output yang berbeda saat menjalankan rilis di dalam Visual Studio, dan menjalankan rilis di luar Visual Studio. Saya menggunakan Visual Studio 2008 dan menargetkan .NET 3.5. Saya juga sudah mencoba .NET 3.5 SP1.
Saat menjalankan di luar Visual Studio, JIT harus masuk. Entah (a) ada sesuatu yang halus terjadi dengan C # yang saya lewatkan atau (b) JIT sebenarnya dalam kesalahan. Saya ragu bahwa JIT bisa salah, tapi saya kehabisan kemungkinan lain ...
Output saat berjalan di dalam Visual Studio:
0 0,
0 1,
1 0,
1 1,
Output saat menjalankan rilis di luar Visual Studio:
0 2,
0 2,
1 2,
1 2,
Apa alasannya?
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();
}
}
}
Jawaban:
Ini adalah bug pengoptimal JIT. Itu membuka gulungan lingkaran dalam tetapi tidak memperbarui nilai oVec.y dengan benar:
Bugnya menghilang ketika Anda membiarkan oVec.y bertambah menjadi 4, itu terlalu banyak panggilan untuk dibatalkan gulungannya.
Salah satu solusinya adalah ini:
UPDATE: diperiksa ulang pada Agustus 2012, bug ini diperbaiki pada versi 4.0.30319 jitter. Tetapi masih ada di jitter v2.0.50727. Sepertinya tidak mungkin mereka akan memperbaikinya dalam versi lama setelah selama ini.
sumber
Saya percaya ini adalah bug kompilasi JIT asli. Saya akan melaporkannya ke Microsoft dan melihat apa yang mereka katakan. Menariknya, saya menemukan bahwa JIT x64 tidak memiliki masalah yang sama.
Inilah bacaan saya tentang JIT x86.
Ini terlihat seperti optimasi yang buruk bagiku ...
sumber
Saya menyalin kode Anda ke Aplikasi Konsol baru.
Jadi itu adalah JIT x86 yang salah menghasilkan kode. Telah menghapus teks asli saya tentang penataan ulang loop dll. Beberapa jawaban lain di sini telah mengkonfirmasi bahwa JIT melepaskan loop yang salah ketika pada x86.
Untuk memperbaiki masalah, Anda dapat mengubah deklarasi IntVec ke kelas dan itu bekerja dalam semua rasa.
Pikirkan ini harus menggunakan MS Connect ....
-1 ke Microsoft!
sumber