Frage

So habe ich eine native 3rd-Party-C ++ Codebasis ich mit (LIB und .hpp Dateien) arbeite, die ich verwendet, um einen Wrapper in C ++ / CLI für eine eventuelle Verwendung in C # zu bauen.

Ich habe in ein bestimmtes Problem führen, wenn sie von Debug-Schaltmodus zu lösen, dass ich eine Zugriffsverletzung Ausnahme erhalten, wenn ein Code kehrt Rückruf.

Der Code von den ursprünglichen HPP-Dateien für Callback-Funktion Format:

typedef int (*CallbackFunction) (void *inst, const void *data);

-Code aus dem C ++ / CLI Wrapper für Callback-Funktion Format: (Ich werde erklären, warum ich zwei in einem Moment deklarierte)

public delegate int ManagedCallbackFunction (IntPtr oInst, const IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);

- Schnell, der Grund, warum ich eine zweite „UnManagedCallbackFunction“ erklärt ist, dass ich versuchte, einen „Vermittler“ Rückruf in der Hülle zu schaffen, so dass die Kette geändert von Native C ++> C # zu einer Version von Native C ++> C ++ / CLI Wrapper> C # ... Vollständige Offenlegung, das Problem immer noch lebt, ist es nur an den C ++ / CLI Wrapper nun auf der gleichen Linie gedrückt wurde (die Rückkehr).

Und schließlich, das Krachen Code von C #:

public static int hReceiveLogEvent(IntPtr pInstance, IntPtr pData)
    {
        Console.WriteLine("in hReceiveLogEvent...");
        Console.WriteLine("pInstance: {0}", pInstance);
        Console.WriteLine("pData: {0}", pData);

        // provide object context for static member function
        helloworld hw = (helloworld)GCHandle.FromIntPtr(pInstance).Target;
        if (hw == null || pData == null)
        {
            Console.WriteLine("hReceiveLogEvent: received null instance pointer or null data\n");
            return 0;
        }

        // typecast data to DataLogger object ptr
        IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataLoggerWrap(pData)));
        DataLoggerWrap dlw = (DataLoggerWrap)GCHandle.FromIntPtr(ip2).Target;

        //Do Logging Stuff

        Console.WriteLine("exiting hReceiveLogEvent...");
        Console.WriteLine("pInstance: {0}", pInstance);
        Console.WriteLine("pData: {0}", pData);
        Console.WriteLine("Setting pData to zero...");
        pData = IntPtr.Zero;
        pInstance = IntPtr.Zero;
        Console.WriteLine("pData: {0}", pData);
        Console.WriteLine("pInstance: {0}", pInstance);

        return 1;
    }

Alle schreiben an die Konsole fertig sind und dann sehen wir den gefürchteten Absturz auf der Rückkehr:

  

Nicht behandelte Ausnahme bei 0x04d1004c in   HelloWorld.exe: 0xC0000005: Zugriffs   Verletzung Leseort 0x04d1004c.

Wenn ich von hier aus in die Debugger Schritt, alles, was ich sehe, ist, dass der letzte Eintrag auf dem Call-Stack ist:> „04d1004c ()“, die in einen Dezimalwert wertet aus: 80.805.964

Welche nur interessant ist, wenn Sie an der Konsole sehen, die zeigen:

entering registerDataLogger
pointer to callback handle: 790848
fp for callback: 2631370
pointer to inst: 790844
in hReceiveLogEvent...
pInstance: 790844
pData: 80805964
exiting hReceiveLogEvent...
pInstance: 790844
pData: 80805964
Setting pData to zero...
pData: 0
pInstance: 0

Nun, ich weiß, dass zwischen Debug und Release einige Dinge in der Microsoft-Welt ganz anders sind. Ich bin natürlich besorgt über die Byte-Polsterung und Initialisierung von Variablen, so dass, wenn es etwas, das ich nicht hier bin bietet, lassen Sie mich einfach wissen und ich werde auf die (bereits lange) Beitrag hinzufügen. Ich denke auch, der verwalteten Code möglicherweise nicht alle Eigentum veröffentlicht und dann das native C ++ Zeug das pData Objekt versuchen, zu löschen oder zu töten (was ich den Code für nicht habe) kann, so dass der App abstürzt.

Weitere vollständige Offenlegung, es funktioniert gut (scheinbar) im Debug-Modus!

Ein echter Kopf kratzt Problem, das jede mögliche Hilfe schätzen würde!

War es hilfreich?

Lösung

ich glaube, der Stapel wurde zerquetscht wegen Aufrufkonventionen unpassenden: versuchen, das Attribut zu setzen

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

auf der Callback-Delegatendeklaration.

scroll top