.net GDI中随机出现的AccessViolationException+;

.net GDI中随机出现的AccessViolationException+;,.net,winforms,.net-2.0,gdi+,access-violation,.net,Winforms,.net 2.0,Gdi+,Access Violation,我们遇到的问题是,有时会发生AccessViolationException,并在一个简单的组框上绘制白色背景和一个红色十字。我们不能可靠地复制这个bug,它只是偶尔发生 我们没有做任何特殊的事情,我们只是显示一个主窗口,其中包含菜单、工具栏、主面板上的组框以及组框内的一些超链接控件 从堆栈跟踪来看,这似乎是Windows窗体或GDI+中的错误: System.AccessViolationException: Attempted to read or write protected memor

我们遇到的问题是,有时会发生
AccessViolationException
,并在一个简单的组框上绘制白色背景和一个红色十字。我们不能可靠地复制这个bug,它只是偶尔发生

我们没有做任何特殊的事情,我们只是显示一个主窗口,其中包含菜单、工具栏、主面板上的组框以及组框内的一些超链接控件

从堆栈跟踪来看,这似乎是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) 

在一切公布之前你打过电话吗?我问了一个类似的问题,在我的位图被销毁之前,我在哪里打过电话,也遇到了访问冲突,我们遇到了类似的问题。 我们有在许多机器上运行的软件,没有问题。在一个Windows XP SP 3上,我们有以下行为:

  • 应用程序正确启动并运行
  • 一段时间后,我们开始从GDI本机代码中获取AccessViolationException。 如果未处理异常,应用程序将停止呈现某些控件或崩溃
  • 违规行为有几个地方,例如:

    1) 异常:System.AccessViolationException
    消息:试图读取或写入受保护内存。这通常表示其他内存已损坏。
    资料来源:系统图

    at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageI(HandleRef graphics, HandleRef image, Int32 x, Int32 y)
    at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y)
    at System.Drawing.Graphics.DrawImageUnscaled(Image image, Int32 x, Int32 y)
    at Aga.Controls.Tree.TreeViewAdv.DrawTree(PaintEventArgs e)
    at Aga.Controls.Tree.TreeViewAdv.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)  
    
    代码似乎没有做任何异常的事情。它将图像渲染到缓冲区,然后调用: e、 Graphics.DrawImageUnscaled(_bufferImage,0,0); 缓冲区不被任何其他线程访问

    (二)

    在这里,
    OnPaint
    方法除了只绘制一行之外,不做任何事情。
    传递给
    绘图线的笔(及其画笔)
    肯定初始化良好,没有处理。

    长话短说。我发现Dot.Net中有一个“bug”,GC将对象从一个地方移动到另一个地方,作为内存优化或碎片整理过程的一部分。这通常发生在将托管内存阵列(或映像)的引用发送到非托管代码段时。数据正在移动到另一个位置,由于未管理的代码没有意识到这一点,因此它尝试访问数据的“旧”位置。这只在发布模式下发生,因为在调试模式下内存优化被关闭,所以始终在发布模式下调试,meh

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

    <> P>我唯一能绕过的方法是手动锁定(PIN)数据并在从未托管代码返回时释放它,是的,返回到C++。图像很棘手,因为您需要在所有类和子类中找到对数据的精确引用


    希望这能有所帮助。

    我以前没见过,但我想这是意料之中的。你说你不能可靠地重新编程。快速解决方案可能是将
    GroupBox
    控件的设置为“System”。当WinForms试图在内部绘制groupbox时,似乎发生了错误;如果让系统来绘制它,您将完全绕过WinForms实现&GDI+。这至少可以让您在找出真正的罪魁祸首时部署一个可用的构建。可能会发布一些代码来帮助我们吗?我应该做的第一件事是启动任务管理器并显示用户对象和GDI对象的计数,以查看应用程序是否泄漏了其中任何一个。你在调用代码中使用了多个线程吗?我不久前遇到过这个问题。我似乎还记得,它依赖于操作系统,是由一个服务包触发的,后来由一个.NET服务包解决了这个问题。真是一派胡言。这不是.net错误,它是经过设计的。
    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.Drawing.Graphics.DrawLine(Pen pen, Point pt1, Point pt2)
    at SomeMyNamespace.SomeMyControl.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.ScrollableControl.WndProc(Message& m)
    at System.Windows.Forms.ContainerControl.WndProc(Message& m)
    at System.Windows.Forms.UserControl.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.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)