GDI+ 中随机发生的 AccessViolationException [英] Randomly occurring AccessViolationException in GDI+

查看:38
本文介绍了GDI+ 中随机发生的 AccessViolationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们遇到的问题是,有时会发生 AccessViolationException 并且绘制一个简单的组框,其背景为白色,顶部有一个红色叉号.我们无法可靠地重现这个错误,它只是不时发生.

We've got the problem that sometimes an AccessViolationException occurs and a simple group box gets drawn with white background and a red cross on top of it. We can't reproducable this bug reliably, it just occurs from time to time.

我们没有做任何特别的事情,我们只是显示一个带有菜单、工具栏、主面板上的分组框和分组框内的一些超链接控件的主窗口.

We don't do anything special, we're just showing a main window with a menu, toolbar, the group box on the main panel and some hyperlink controls inside the group box.

从堆栈跟踪来看,它似乎是 Windows Forms 或 GDI+ 中的一个错误:

From the stack trace it seems to be a bug in Windows Forms or GDI+:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Drawing.SafeNativeMethods.Gdip.GdipDrawLineI(HandleRef graphics, HandleRef pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
   at System.Drawing.Graphics.DrawLine(Pen pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
   at System.Windows.Forms.GroupBox.DrawGroupBox(PaintEventArgs e)
   at System.Windows.Forms.GroupBox.OnPaint(PaintEventArgs e)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.GroupBox.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

推荐答案

长话短说.我发现 Dot.Net 中有一个错误",其中对象被 GC 从一个地方移动到另一个地方,作为内存优化或碎片整理过程的一部分.这通常发生在将托管内存阵列(或图像)的引用发送到非托管代码段时.数据被移动到不同的位置,由于非托管代码不知道这一点,它试图访问数据的旧"位置.这仅在发布模式下发生,因为在调试模式下内存优化已关闭,因此始终在发布模式下进行调试,嗯...

To make long story short. I found out that there is a ""bug"" in Dot.Net where objects are moved by the GC from one place to the other as part of memory optimization or Defragmentation process. This usually happens when sending a reference of a managed memory array (or image) to an un-managed piece of code. The data is being moved to a different location and as the un-managed code is not aware of this it tries to access the "old" location of the data. This only happens in Release mode as in Debug mode memory optimization is switched off so ALWAYS debug in Release mode, meh...

不幸的是,没有办法关闭 GC 碎片整理过程.您可以尝试调用 GC.Collect() 并等待它完成,然后再调用您的 GDI+ 函数,但这只会改善情况并不能完全解决问题.

Unfortunately, there is no way to turn off the GC defragmentation process. You can try and call the GC.Collect() and wait for it to finish before calling your GDI+ function but this will only improve the situation and not solve it completely.

我能够绕过这个的唯一方法是手动锁定(固定)数据并在从非托管代码返回后释放它,是的,回到 C++.图片很棘手,因为您需要在所有类和子类中找到对数据的确切引用.

The only way I was able to bypass this is to manually lock (pin) the data and release it after returned from the un-managed code, yes, back to C++. Images are tricky as you need to find the exact reference to the data in all the classes and sub-classes.

希望这会有所帮助.

这篇关于GDI+ 中随机发生的 AccessViolationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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