访问冲突异常/崩溃从C ++回调到C#功能

问题描述:

所以我有一个本土第三方C ++代码库,我与我用来建立在C#中最终使用在C ++ / CLI的包装(.LIB和.HPP文件)工作。

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#.

我从调试切换到发布模式时碰到一个特殊的问题,因为我得到一个访问冲突异常时一个回调的代码返回。

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.

从回调函数的格式原来的HPP文件的代码:

The code from the original hpp files for callback function format:

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

代码从C ++ / CLI包装的回调函数格式为:
(我会解释为什么我宣布在某一时刻二)

Code from the C++/CLI Wrapper for callback function format: (I'll explain why I declared two in a moment)

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



- 很快,我宣布第二个UnManagedCallbackFunction的原因是,我试图创建一个中介回调在包装,所以链从本地C ++> C#改为版本本地C ++> C ++ / CLI包装> C#...全文披露,问题仍然生活,它只是被推迟到C ++ / CLI包装的现在在同一行(返回)

--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).

最后,从C#的崩溃代码:

And finally, the crashing code from 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;
    }



所有写操作完成后控制台,然后我们看到了可怕的崩溃返回:

All writes to the console are done and then we see the dreaded crash on the return:


HelloWorld.exe的0x04d1004c未处理的异常:0000005:访问
冲突读取位置0x04d1004c

Unhandled exception at 0x04d1004c in helloworld.exe: 0xC0000005: Access violation reading location 0x04d1004c.

如果我踏进从这里调试器,我看到的是,在调用堆栈中的最后一项是:>04d1004c() 所求的十进制值:80805964

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

如果你看一下它显示控制台,它是唯一感兴趣的:

Which is only interesting if you look at the console which shows:

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

现在,我知道,调试之间释放一些东西都在微软的世界完全不同。我当然担心字节填充和变量的初始化,所以如果有什么我这里不提供,只是让我知道,我会加入到(已长)职务。我也认为,托管代码可能不释放所有所有权,然后在本地C ++的东西(我不具备的代码)可能试图删除或杀死的pData中的对象,从而崩溃的应用程序。

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.

更充分披露,这一切都在调试模式下正常工作(貌似)!

More full disclosure, it all works fine (seemingly) in Debug mode!

一个真正的头划伤的问题,希望得到任何!帮助

A real head scratch issue that would appreciate any help!

我想是因为不匹配调用约定的协议栈得到粉碎:
尝试把属性

I think the stack got crushed because of mismatching calling conventions: try out to put the attribute

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

在回调委托声明。