【问题标题】:What does it mean when a .NET application crashes due to a System.AccessViolation exception?当 .NET 应用程序由于 System.AccessViolation 异常而崩溃时,这意味着什么?
【发布时间】:2014-11-01 00:18:26
【问题描述】:

应用程序本身有 2000 行长,因此在此处粘贴代码是没有意义的,尤其是因为其中一位用户收到的异常没有提供任何提示,说明我的代码的哪一部分导致了问题。

顺便说一句,该应用程序只是一个 Windows 窗体,带有一个通常显示不超过几百行数据的 datagridview 和一些其他控件。在它崩溃之前,它加载 datagridview 每一行的单元格的速度非常慢。 (但没有其他用户遇到过同样的问题。)

异常文本如下。有人可以查看它并告诉我这是否是由于我的代码做错了什么或者可能与遇到此异常的用户的特定设置不兼容造成的?

我注意到下面的描述说内存已损坏。是不是表示用户的电脑内存不好???

  ************** Exception Text **************
  System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
     at System.Drawing.SafeNativeMethods.Gdip.GdipDrawRectangleI(HandleRef graphics, HandleRef pen, Int32 x, Int32 y, Int32 width, Int32 height)
     at System.Drawing.Graphics.DrawRectangle(Pen pen, Int32 x, Int32 y, Int32 width, Int32 height)
     at System.Windows.Forms.ControlPaint.DrawFlatCheckBox(Graphics graphics, Rectangle rectangle, Color foreground, Brush background, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawFlatCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawCheckBox(Graphics graphics, Int32 x, Int32 y, Int32 width, Int32 height, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state)
     at System.Windows.Forms.CheckedListBox.OnDrawItem(DrawItemEventArgs e)
     at System.Windows.Forms.ListBox.WmReflectDrawItem(Message& m)
     at System.Windows.Forms.ListBox.WndProc(Message& m)
     at System.Windows.Forms.CheckedListBox.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)

【问题讨论】:

  • 要么是内存损坏,要么是winforms的bug。
  • 内存损坏可能意味着在某个时间点、某处有内存覆盖。应用程序是否在任何地方使用unsafe 代码?
  • 没有。此应用没有不安全代码。
  • 有 2 个选项。要么用户确实有坏的物理内存,要么应用程序在某处使用非托管代码错误地将值写入内存。与内存问题相比,它更有可能是软件问题。异常的调用堆栈是否总是相同的?如果是,那么几乎可以肯定是软件问题。您是否使用任何第三方组件?
  • 你修改了自动生成的表单设计器代码吗?

标签: c# .net forms exception


【解决方案1】:

没有更多代码,很难准确地说。这里有一些注意事项。

.NET 是一个托管环境,其基本原则之一是能够在编译时验证代码。具体来说,这意味着可以对一个代码单元做出某些保证,例如:

  • 无法读取超出数组范围的内容
  • 无法修改函数指针
  • 无法读取/修改内存代码段
  • 无法混淆对象引用的类型

尝试执行这些操作要么在编译时失败,要么在运行时出现异常。

您看到的异常是“不安全”代码的结果。 Unsafe 确实有点用词不当——最好将其描述为“无法验证”。有时,出于性能原因,有必要放弃代码的可验证性,以通过指针算法等方式换取原始速度。

此应用没有不安全的代码。

WinForms 广泛使用“不安全”代码。更准确地说,您的程序集没有任何不安全代码,但它依赖于不安全的库代码。

我注意到下面的描述说内存已损坏。是不是表示用户的电脑内存不好?

内存坏是有可能的,但不太可能。当预期存在的值实际上不存在时,内存已损坏。这可能是由于硬件故障,也可能是软件错误。根据我的经验,通常会引发此异常以响应软件错误。消息还说内存可能已损坏。

此处的堆栈跟踪实际上可能不是很有洞察力,因为内存可能在较早的时候已损坏,并且仅在您在此处看到的堆栈帧期间检测到。

对 user32.dll 的 ShowWindow 函数 (ShowWindow(p.MainWindowHandle, SW_SHOWDEFAULT);) 有 1 个平台调用调用,但此调用发生在消息循环开始之前。

这很可能是罪魁祸首。您是否尝试过使用托管的Window.Show 方法?可能是您的窗口还没有句柄,或者它发生了变化,或者因此出现了许多问题。在原生内容之上使用托管包装器时,通常尽量避免 PInvoke。

很遗憾,如果没有看到更多代码,就不可能提供更有用的答案,但希望以上内容为异常提供了一些上下文,并可以帮助您了解您的应用程序正在做什么以使 WinForms 进入此状态。

【讨论】:

  • “WinForms 广泛使用了‘不安全’代码。更准确地说,你的程序集没有任何不安全代码,但它依赖于不安全的库代码。”感谢您的回答。这很有帮助:)
【解决方案2】:

我想提一下这一点,因为我突然出现了这个异常,我花了几天时间才弄明白。我不知道上面的问题是否相关,但也许它会帮助那些来搜索所述异常的人。

我正在测试一些日志记录代码,一旦签入测试,我们会看到构建服务器上弹出异常。我们无法在我们的开发机器上本地重新创建它。

我决定将逻辑从构造函数移到方法中,突然异常变为 System.EntryPointNotFoundException!

在我们的测试工具中,我们使用记录器未引用的 System.WebAPI 排列对象。引用正确的库解决了这个问题。

TL;DR;当你看到这个异常时,不要将你的业务逻辑放在一个 Ctor 中并检查你的引用。

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    相关资源
    最近更新 更多