导致AccessViolationException的未受管的DLL [英] Unmanaged DLL causing AccessViolationException

查看:169
本文介绍了导致AccessViolationException的未受管的DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这真的开始让我头疼:(

This one is really starting to give me a headache :(

我有一个非托管DLL,我试图互操作,它不顺利。应用程序有时会工作,但大多数时候,随机通过AccessViolationException和崩溃可怕。

I have an unmanaged DLL that I'm trying to interop with and it's not going well. The application will sometimes work...but most times, randomly through an AccessViolationException and crash horribly.

我想我已经缩小到我错误处理一个单一的DllImport:

I think I've narrowed it down to my mishandling of a single DllImport:

C ++函数:

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

C#DllImport:

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 是一个罪魁祸首,但不知道如何证明它!

Is there anything glaringly wrong with this? I suspect that dataSource is a culprit but...not sure how to prove it!

>

推荐答案

您的问题可以从函数的名称推断。当你设置一个缓冲区时,很可能本地代码稍后将使用该缓冲区。这与垃圾收集器不兼容,它会在压缩堆时移动数组。这是一个大的Kaboom,当本机代码写入缓冲区时,它将写入不再存在的内存。最典型的结果是当垃圾收集器检测到堆完整性被破坏时,发生FatalExecutionEngineException。

Your problem can be inferred from the name of the function. When you "set a buffer", it is likely that the native code is going to use that buffer later. That's incompatible with the garbage collector, it is going to move the array when it compacts the heap. That's a big Kaboom when the native code then writes to the buffer, it is going to write to memory that isn't there anymore. The most typical outcome is a FatalExecutionEngineException when the garbage collector detects that the heap integrity got compromised.

数组需要被固定,pinvoke marshaller在调用

The array needs to be pinned, something that the pinvoke marshaller does when it calls the function, but it unpins the array after the call.

您可以使用GCHandle.Alloc()固定一个托管数组,但这是漂亮的对垃圾收集器有害,如果你把它固定了很长时间。到目前为止,最好的解决方案是使用Marshal.AllocHGlobal分配一个非托管内存块,它从不移动。

You can pin a managed array with GCHandle.Alloc(), but that's pretty detrimental to the garbage collector if you leave it pinned for a long time. By far the best solution is to use Marshal.AllocHGlobal to allocate a chunk of unmanaged memory, it never moves.

如果你仍然有麻烦,那么担心的大小缓冲。而在本地代码中只是纯粹的苦难,它很少需要很多帮助跌倒AccessViolation。这是本机代码的标准故障模式。很难诊断,不可能如果你没有它的源代码。请与代码所有者联系以获得支持,并提供一个小型重现代码段,以帮助他找到问题所在。

If you still have trouble then worry about the size of the buffer. And just plain misery in the native code, it rarely needs much help to fall over on an AccessViolation. That's the standard failure mode for native code. Very hard to diagnose, impossible if you don't have the source code for it. Contact the code owner for support, have a small repro snippet available to help him locate the problem.

这篇关于导致AccessViolationException的未受管的DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆