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.