我们遇到的问题是有时 AccessViolationException
会出现一个简单的组框,它带有白色背景,上面有一个红十字。我们无法可靠地重现此错误,它只是不时发生。
我们没有做任何特别的事情,我们只是显示一个带有菜单、工具栏、主面板上的分组框和分组框内的一些超链接控件的主窗口。
从堆栈跟踪来看,它似乎是 Windows Forms 或 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 从一个地方移动到另一个地方,作为内存优化或碎片整理过程的一部分。这通常发生在将托管内存数组(或图像)的引用发送到非托管代码段时。数据被移动到不同的位置,由于非托管代码不知道这一点,它试图访问数据的“旧”位置。这仅在 Release模式下发生,因为在 Debug模式下内存优化已关闭,因此始终在 Release模式下进行调试,嗯...
不幸的是,没有办法关闭 GC 碎片整理过程。
您可以尝试调用 GC.Collect() 并等待它完成,然后再调用您的 GDI+ 函数,但这只会改善情况并不能完全解决问题。
我能够绕过这个的唯一方法是手动锁定(固定)数据并在从非托管代码返回后释放它,是的,回到 C++。图像很棘手,因为您需要在所有类和子类中找到对数据的确切引用。
希望这会有所帮助。
关于.net - GDI+ 中随机发生的 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5510115/