IL läuft unter Release nicht

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Bluespide.

    IL läuft unter Release nicht

    Moin zusammen,

    ich habe folgende Signatur einer Funktion ​public static byte[] Test<T>(T ojb) where T : struct { die mir ein Struct mit ​[StructLayout(LayoutKind.Sequential, Pack = 1)] in ein ByteArray umwandeln soll. Weil das im IL schneller gehen sollte habe ich diese manuell im IL mal gebaut.



    So weit so gut, das funktioniert auch. Jetzt wollte ich das ganze als DynamicMethod nachbauen:

    C#-Quellcode

    1. ​private static Func<T, byte[]> CreateDelegate() {
    2. DynamicMethod dm = new DynamicMethod("Serialize" + typeof(T).Name, typeof(byte[]), new[] { typeof(T) }, Assembly.GetExecutingAssembly().ManifestModule);
    3. dm.DefineParameter(1, ParameterAttributes.None, "obj");
    4. ILGenerator generator = dm.GetILGenerator();
    5. generator.Emit(OpCodes.Sizeof, typeof(T));
    6. generator.Emit(OpCodes.Newarr, typeof(byte));
    7. generator.Emit(OpCodes.Dup);
    8. generator.Emit(OpCodes.Ldc_I4_0);
    9. generator.Emit(OpCodes.Ldelema, typeof(byte));
    10. generator.Emit(OpCodes.Ldarg_0);
    11. generator.Emit(OpCodes.Cpobj, typeof(T));
    12. generator.Emit(OpCodes.Ret);
    13. return (Func<T, byte[]>)dm.CreateDelegate(typeof(Func<T, byte[]>));
    14. }


    Das ganze läuft im Debug, aber nicht im Release. Im Release bekomme ich eine NullReferenceException. Ich weiß, das ist jetzt ein bisschen schwer zu analysieren, aber hat jemand eine Idee, warum es im Debug geht aber im Release nicht?
    Hi
    bei mir funktioniert es in beiden. Beachte aber, dass das Byte-Array wohl angepinnt werden sollte, bevor du darauf operierst.

    Außerdem wäre es ggf. sinnvoller, ein Byte-Array übergeben zu lassen und nicht, es neu zu generieren:

    C#-Quellcode

    1. void Serialize(T obj, byte[] buffer, int index)


    Viele Grüße
    ~blaze~
    Mh, ich war die ganze Zeit mit x64 unterwegs. Bei x86 gibt es keine Exception, aber es kommen gar nicht die richtigen Daten im Array an :huh: . Da muss ich mich wohl nochmal genauer mit beschäftigen. Ich werde das mit dem Pinnen mal versuchen.

    ~blaze~ schrieb:

    Außerdem wäre es ggf. sinnvoller, ein Byte-Array übergeben zu lassen und nicht, es neu zu generieren:

    Jo die hatte ich auch schon als Überladung und die hat unter x64 auch soweit funktioniert in beiden Debug und Release.
    Auch die Release-Konfiguration kann debuggt werden.
    Rechtsklick im Projektmappenexplorer auf die Projektmappe (nicht das Projekt) und dann Eigenschaften.

    Dann Konfigurationseigenschaften auswählen.
    Bei "Konfiguration" links oben "Debug" auswählen.
    Dann in der Liste beim Projekt, das du im Release-Modus debuggen willst, bei der Spalte "Konfiguration" "Release" auswählen.

    Speichern und debuggen.
    Du erkennst, dass es funktioniert, wenn in so einem Code:

    C#-Quellcode

    1. if (irgendwas)
    2. {
    3. Foo();
    4. }

    bei einem Einzelschritt von Zeile 1 direkt auf Zeile 3 gesprungen wird, anstatt wie im Debug-Modus von Zeile 1 zu Zeile 2, dann erst zu 3 und dann zu 4 (das passiert, weil im Debug-Modus NOP-Anweisungen für die öffnenden und schließenden Klammern im IL eingebaut werden).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Habs gelöst. Es liegt am ​cpobj. Wenn ich das durch ​stobj ersetzen und zusammen mit dem anpinnen benutzte funktionierts.

    C#-Quellcode

    1. private static Func<T, byte[]> CreateDelegate() {
    2. DynamicMethod dm = new DynamicMethod("Serialize" + typeof(T).Name, typeof(byte[]), new[] { typeof(T) }, Assembly.GetExecutingAssembly().ManifestModule);
    3. ILGenerator generator = dm.GetILGenerator();
    4. generator.DeclareLocal(typeof(byte).MakeByRefType(), true);
    5. generator.Emit(OpCodes.Sizeof, typeof(T));
    6. generator.Emit(OpCodes.Newarr, typeof(byte));
    7. generator.Emit(OpCodes.Dup);
    8. generator.Emit(OpCodes.Ldc_I4_0);
    9. generator.Emit(OpCodes.Ldelema, typeof(byte));
    10. generator.Emit(OpCodes.Stloc_0);
    11. generator.Emit(OpCodes.Ldloc_0);
    12. generator.Emit(OpCodes.Ldarg_0);
    13. generator.Emit(OpCodes.Stobj, typeof(T));
    14. generator.Emit(OpCodes.Ret);
    15. return (Func<T, byte[]>)dm.CreateDelegate(typeof(Func<T, byte[]>));
    16. }