gpt4 book ai didi

c# - 从 C++ 回调到 C# 函数的访问冲突异常/崩溃

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:14 25 4
gpt4 key购买 nike

因此,我有一个正在使用的 native 第 3 方 C++ 代码库(.lib 和 .hpp 文件),我曾使用它在 C++/CLI 中构建包装器以最终在 C# 中使用。

从 Debug模式切换到 Release模式时,我遇到了一个特殊问题,因为当回调的代码返回时,我得到了一个访问冲突异常。

原始hpp文件中回调函数格式的代码:

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

回调函数格式的 C++/CLI Wrapper 代码:(稍后我会解释为什么我声明了两个)

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

-- 很快,我声明第二个“UnManagedCallbackFunction”的原因是我试图在包装器中创建一个“中间”回调,因此链从 Native C++ > C# 更改为 Native C++ > C++/CLI 的版本Wrapper > C#...完全公开,问题仍然存在,它现在被推送到同一行的 C++/CLI Wrapper(返回)。

最后,来自 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;
}

所有对控制台的写入都已完成,然后我们在返回时看到可怕的崩溃:

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

如果我从这里进入调试器,我所看到的是调用堆栈中的最后一个条目是:>“04d1004c()”,它的十进制值为:80805964

只有当您查看显示以下内容的控制台时,这才是有趣的:

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

现在,我知道在 Microsoft 世界中调试和发布之间有些事情是完全不同的。我当然担心变量的字节填充和初始化,所以如果有什么我没有在这里提供,请告诉我,我会添加到(已经很长的)帖子中。我还认为托管代码可能不会释放所有所有权,然后 native C++ 东西(我没有代码)可能会尝试删除或杀死 pData 对象,从而使应用程序崩溃。

更全面的披露,它在 Debug模式下一切正常(看似)!

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

最佳答案

我认为堆栈由于不匹配的调用约定而被压垮:尝试放置属性

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

关于回调委托(delegate)声明。

关于c# - 从 C++ 回调到 C# 函数的访问冲突异常/崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1411110/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com