非托管的DLL导致AccessViolationException(Unmanaged DLL ca

2019-09-20 06:37发布

这一个是真的开始让我头疼:(

我有我想要一起互操作的非托管的DLL,它的并不顺利。 该应用程序有时会工作......但大多数时候,随机通过AccessViolationException和可怕的崩溃。

我想我已经收窄,到我的单一的DllImport处理不当:

C ++函数:

HTMLRENDERERDLL_REDIST_API void SetDataBuffer( int windowHandle, unsigned char* dataSource, int format, int stride, int totalBufferSize );

C#的DllImport:

[DllImport("MyDll.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    static private extern unsafe void SetDataBuffer(Int32 windowHandle, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] dataSource, Int32 format, Int32 stride, Int32 totalBufferSize);

呼吁说功能:

var buffer = new byte[windowWidth * windowHeight * bytesPerPixel];
SetDataBuffer(windowHandle, buffer, (Int32)0, (Int32)(windowWidth * bytesPerPixel), (Int32)(windowWidth * windowHeight * bytesPerPixel));

这有什么错得离谱这个? 我怀疑dataSource是罪魁祸首,但......不知道如何来证明这一点!

谢谢

Answer 1:

你的问题可以从函数的名称来推断。 当“设置一个缓冲区”,很可能是本机代码会在以后使用该缓冲区。 这是与垃圾回收器不兼容,这是怎么回事,当压缩堆移动阵列。 这是一个很大KABOOM当本机代码,然后写入缓冲区,它要写入内存是不存在了。 最典型的结果是一个FatalExecutionEngineException当垃圾收集器检测到堆的完整性得到了损害。

该阵列需要进行固定的东西,当它调用的功能,但它unpins调用后数组中的PInvoke编组一样。

你可以用针GCHandle.Alloc()托管数组,但如果你把它别住了很长一段时间那是相当有害的垃圾收集器。 到目前为止,最好的解决办法是使用Marshal.AllocHGlobal分配非托管内存的一大块,它永远不会移动。

如果您仍然有问题再担心缓冲区的大小。 而且在本机代码只是简单的苦难,但很少需要太大的帮助摔倒上AccessViolation。 这对本地代码的标准故障模式。 非常难以诊断的,不可能的,如果你没有为它的源代码。 联系码所有者的支持,有可用来帮助他找到问题的一个小摄制片段。



Answer 2:

我认为,很可能是数据源的问题。

尝试让它使用一个IntPtr,而不是字节[]改变dllimport的。

[DllImport("MyDll.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
static private extern unsafe void SetDataBuffer(Int32 windowHandle, IntPtr dataSource, Int32 format, Int32 stride, Int32 totalBufferSize);

然后,当你调用它,明确分配的内存,像这样的缓冲:

IntPtr buffer = Marshal.AllocHGlobal(windowWidth * windowHeight * bytesPerPixel);
SetDataBuffer(windowHandle, buffer, (Int32)0, (Int32)(windowWidth * bytesPerPixel), (Int32)(windowWidth * windowHeight * bytesPerPixel));

而且不要忘记调用Marshal.FreeHGlobal(buffer)当您完成用它做。

我认为缓冲区正在被更新方法内部使用?



文章来源: Unmanaged DLL causing AccessViolationException
标签: c# c++ dll interop