Note that there are some explanatory texts on larger screens.

plurals
  1. POAccess Violation Exception/Crash from C++ callback to C# function
    primarykey
    data
    text
    <p>So I have a native 3rd party C++ code base I am working with (.lib and .hpp files) that I used to build a wrapper in C++/CLI for eventual use in C#. </p> <p>I've run into a particular problem when switching from Debug to Release mode, in that I get an Access Violation Exception when a callback's code returns. </p> <p>The code from the original hpp files for callback function format:</p> <pre><code>typedef int (*CallbackFunction) (void *inst, const void *data); </code></pre> <p>Code from the C++/CLI Wrapper for callback function format: (I'll explain why I declared two in a moment)</p> <pre><code>public delegate int ManagedCallbackFunction (IntPtr oInst, const IntPtr oData); public delegate int UnManagedCallbackFunction (void* inst, const void* data); </code></pre> <p>--Quickly, the reason I declared a second "UnManagedCallbackFunction" is that I tried to create an "intermediary" callback in the wrapper, so the chain changed from Native C++ > C# to a version of Native C++ > C++/CLI Wrapper > C#...Full disclosure, the problem still lives, it's just been pushed to the C++/CLI Wrapper now on the same line (the return).</p> <p>And finally, the crashing code from C#:</p> <pre><code>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; } </code></pre> <p>All writes to the console are done and then we see the dreaded crash on the return:</p> <blockquote> <p>Unhandled exception at 0x04d1004c in helloworld.exe: 0xC0000005: Access violation reading location 0x04d1004c.</p> </blockquote> <p>If I step into the debugger from here, all I see is that the last entry on the call stack is: > "04d1004c()" which evaluates to a decimal value of: 80805964</p> <p>Which is only interesting if you look at the console which shows: </p> <pre><code>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 </code></pre> <p>Now, I know that between debug and release some things are quite different in the Microsoft world. I am, of course worried about byte padding and initialization of variables, so if there is something I am not providing here, just let me know and I'll add to the (already long) post. I also think the managed code may NOT be releasing all ownership and then the native C++ stuff (which I don't have the code for) may be trying to delete or kill off the pData object, thus crashing the app.</p> <p>More full disclosure, it all works fine (seemingly) in Debug mode!</p> <p>A real head scratch issue that would appreciate any help!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload