6 Stimmen

Die Kompilierung lässt Code nach festen Blöcken in bestimmten Methoden aus.

Wir haben die folgende Methode in einer Klasse in einem unserer Projekte:

private unsafe void SomeMethod()
{
    // Anfang der Methode weggelassen aus Gründen der Kürze

    var nv = new Vector4[x];

    fixed (Vector4* vp = nv)
    {
        fixed (float* tp = /* Source float ptr */)
        {
            fixed (double* ap = /* Source double ptr */)
            {
                for (var i = atlArray.Length - 1; i >= 0; --i)
                {
                    vp[((i + 1) << 3) - 2] = new Vector4(tp[i], btt, 0.0f, 1.0f);
                    // Zusätzliche Vector4-Konstruktion aus Gründen der Kürze weggelassen

                    nttp[i] = new Vector2(tp[i], this.ttvp);
                    nts[i] = string.Format(ap[i], /* etc. */);
                }
            }
        }
    }

    this.ts = nts;
    this.ttp = nttp;
    this.V = nv; // <- Dies ist ein Eigenschafts-Setter
}

Ich musste dies etwas unkenntlich machen, aber hoffentlich ist es immer noch klar genug, um eine Vorstellung davon zu bekommen, was passiert.

Auf einem der Entwicklermaschinen entfernt der C#-Compiler in Debug-Builds die drei Zuweisungen, die nach dem Schließen des fixed-Blocks erfolgen. Wenn wir versuchen, einen Haltepunkt auf diesen Zeilen zu setzen, springt der Haltepunkt beim Start der Anwendung zur abschließenden Klammer der Methode. Code, der zwischen einem fixed-Block und dem Ende einer Methode erscheint, wird auch in anderen Methoden entfernt, aber verwirrenderweise nicht in allen.

Nach einigen Experimenten fanden wir heraus, dass das Einschalten der Optimierung für das betroffene Projekt dazu führt, dass der fehlende Code eingeschlossen wird. Allerdings funktioniert dieser Workaround nicht für unsere Unit-Tests - der Code fehlt, und das Ändern der Optimierung des betroffenen Projekts und seines Testprojekts hilft nicht. Wir fanden auch heraus, dass das Verschieben der drei Zuweisungen innerhalb des innersten fixed-Statements funktioniert - das wird deutlich, wenn man den IL-Code untersucht.

In der Debug-DLL, die auf der betroffenen Maschine erstellt wurde (mit deaktivierter Optimierung), erscheint ein Rückgabebefehl direkt nachdem ap vom Stapel genommen wird:

IL_03a1:  nop
IL_03a2:  ldc.i4.0
IL_03a3:  conv.u
IL_03a4:  stloc.s    ap
IL_03a6:  ret

Dies erklärt, warum das Verschieben der drei Zuweisungen vor der stloc-Anweisung funktioniert. In der Debug-DLL, die auf meiner Maschine erstellt wurde, tritt der Rückgabebefehl am erwarteten Ort auf, nach den drei Zuweisungen:

IL_03a5:  nop
IL_03a6:  ldc.i4.0
IL_03a7:  conv.u
IL_03a8:  stloc.s    ap
IL_03aa:  nop
IL_03ab:  ldc.i4.0
IL_03ac:  conv.u
IL_03ad:  stloc.s    tp
IL_03af:  nop
IL_03b0:  ldc.i4.0
IL_03b1:  conv.u
IL_03b2:  stloc.s    vp
IL_03b4:  ldarg.0
IL_03b5:  ldloc.s    nts
IL_03b7:  stfld      string[] N.B.E.B::ts
IL_03bc:  ldarg.0
IL_03bd:  ldloc.s    nttp
IL_03bf:  stfld      valuetype [SharpDX]SharpDX.Vector2[] N.B.E.B::ttp
IL_03c4:  ldarg.0
IL_03c5:  ldloc.s    nv
IL_03c7:  call       instance void N.B.E.B::set_V(valuetype [SharpDX]SharpDX.Vector4[])
IL_03cc:  nop
IL_03cd:  ret

Bisher ist uns die Erstellung eines SSCCE nicht gelungen - dies scheint nur unter sehr spezifischen Umständen und nur in einem unserer Projekte aufzutreten. Wir haben überprüft, dass auf beiden Maschinen die gleichen Versionen von Visual Studio, dem .NET Framework, dem C#-Compiler und MSBuild verwendet werden. Wir haben andere potenzielle Unterschiede wie die Betriebssystemversion und Updates überprüft. Die Dinge scheinen auf beiden Maschinen gleich zu sein (es handelt sich um dasselbe Laptop-Modell). Wir sind ehrlich gesagt etwas verwirrt. Jede Hilfe wäre sehr willkommen.

0voto

Chris Mantle Punkte 6499

Mein Kollege, der Entwickler, dessen Maschine betroffen war, fand einen Unterschied in der Diagnoseausgabe des Builds - es war der C#-Compiler. Wir dachten, dass MSBuild den csc.exe im erwarteten Ort (c:\Program Files (x86)\MSBuild\12.0\Bin) verwendete, aber seltsamerweise wurde tatsächlich eine csc.exe in C:\Benutzer\[Benutzer]\AppData\Lokal\Microsoft\VisualStudio\12.0\Erweiterungen ausgeführt, die eine komplett andere Version hatte. Wir wissen nicht, wie dieser Compiler-Executable dort gelandet ist oder wie er von MSBuild referenziert wurde, aber nachdem er entfernt wurde, hat MSBuild wieder auf die Version von csc.exe in seinem eigenen Bin-Verzeichnis zurückgegriffen und der Code wird jetzt korrekt erstellt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X