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

查看:166
本文介绍了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天全站免登陆