winforms GDI+中随机发生的访问违规异常

pw9qyyiw  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(181)

我们遇到了一个问题,有时会出现AccessViolationException,一个简单的分组框被画成白色背景,上面有一个红色的十字。我们不能可靠地重现这个错误,它只是偶尔发生。
我们没有做任何特别的事情,我们只是显示一个主窗口,其中有一个菜单、工具栏、主面板上的分组框和分组框内的一些超链接控件。
从堆栈跟踪来看,这似乎是Windows窗体或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)
xqnpmsa8

xqnpmsa81#

在. Net中,GC将对象从一个位置移动到另一个位置,作为内存优化或碎片整理过程的一部分。这通常发生在将托管内存数组(或映像)的引用发送到非托管代码段时。
数据被移动到不同的位置,由于非托管代码不知道这一点,它试图访问数据的“旧”位置。这只发生在发布模式下,因为在调试模式下内存优化被关闭,所以总是在发布模式下调试,meh...
不幸的是,没有办法关闭GC碎片整理过程。您可以尝试调用GC.Collect(),并等待它完成后再调用GDI+函数,但这只能改善情况,而不能完全解决问题。
我能够绕过这一点的唯一方法是手动锁定(pin)数据,并在从非托管代码返回后释放它,是的,返回到C++。图像是棘手的,因为您需要在所有类和子类中找到对数据的确切引用。

tcbh2hod

tcbh2hod2#

我问了一个类似的问题here,我在位图被破坏之前调用了GdiplusShutdown,也得到了访问冲突

相关问题