Le code suivant donne une sortie différente lors de l'exécution de la version dans Visual Studio et de l'exécution de la version en dehors de Visual Studio. J'utilise Visual Studio 2008 et je cible .NET 3.5. J'ai également essayé .NET 3.5 SP1.
Lors de l'exécution en dehors de Visual Studio, le JIT doit démarrer. Soit (a) il se passe quelque chose de subtil avec C # qui me manque ou (b) le JIT est en fait en erreur. Je doute que le JIT puisse mal tourner, mais je suis à court d'autres possibilités ...
Sortie lors de l'exécution dans Visual Studio:
0 0,
0 1,
1 0,
1 1,
Sortie lors de l'exécution d'une version en dehors de Visual Studio:
0 2,
0 2,
1 2,
1 2,
Quelle est la raison?
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();
}
}
}
Réponses:
Il s'agit d'un bogue d'optimiseur JIT. Il déroule la boucle interne mais ne met pas à jour la valeur oVec.y correctement:
Le bogue disparaît lorsque vous laissez oVec.y incrémenter à 4, c'est trop d'appels à dérouler.
Une solution de contournement est la suivante:
MISE À JOUR: revérifié en août 2012, ce bug a été corrigé dans la gigue de la version 4.0.30319. Mais est toujours présent dans la gigue v2.0.50727. Il semble peu probable qu'ils corrigent ce problème dans l'ancienne version après une longue période.
la source
Je crois que c'est dans un véritable bug de compilation JIT. Je voudrais le signaler à Microsoft et voir ce qu'ils disent. Fait intéressant, j'ai trouvé que le JIT x64 n'a pas le même problème.
Voici ma lecture du x86 JIT.
Cela ressemble à une optimisation qui a mal tourné pour moi ...
la source
J'ai copié votre code dans une nouvelle application console.
C'est donc le JIT x86 qui génère incorrectement le code. J'ai supprimé mon texte d'origine sur la réorganisation des boucles, etc. Quelques autres réponses ici ont confirmé que le JIT déroule la boucle de manière incorrecte lorsqu'il est sur x86.
Pour résoudre le problème, vous pouvez modifier la déclaration d'IntVec en classe et cela fonctionne dans toutes les versions.
Pensez que cela doit aller sur MS Connect ....
-1 à Microsoft!
la source