我是一名有用的助手,可以为您进行文本翻译。
我正在处理一个本地第三方C++代码库(.lib和.hpp文件),并使用它构建了一个C++/CLI封装器,最终将其用于C#。
当我从调试模式切换到发布模式时,我遇到了一个特定的问题,即当回调函数的代码返回时,我会收到一个访问冲突异常。
回调函数格式的原始hpp文件的代码如下:
typedef int (*CallbackFunction) (void *inst, const void *data);
C++/CLI包装器中回调函数格式的代码: (稍后我会解释为什么我声明了两个)
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包装器 > C#的版本...全面披露,问题仍然存在,只是现在被推到了同一行的C++/CLI包装器(返回)上。
最后,来自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;
}
所有写入控制台的内容都已完成,然后我们看到了可怕的崩溃:
在helloworld.exe中未处理的异常 0x04d1004c:0xC0000005:访问位置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
现在,我知道在微软世界中,在调试和发布之间有一些非常不同的事情。 当然,我担心的是字节填充和变量初始化问题,因此,如果我没有提供某些内容,请告诉我,我会添加到(已经很长的)帖子中。 我还认为托管代码可能没有释放所有权,然后本机C ++(我没有代码)可能尝试删除或杀死pData对象,从而导致应用程序崩溃。
更全面的披露,Debug模式下一切似乎都很正常!
这是一个真正的令人头疼的问题,非常感谢任何帮助!