4

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

顺便说一句,该应用程序只是一个带有 datagridview 的 Windows 窗体,通常显示不超过几百行数据和一些其他控件。在它崩溃之前,它加载 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)
4

2 回答 2

5

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

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

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

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

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

这个应用程序没有不安全的代码。

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

我注意到下面的描述说内存已损坏。这是否意味着用户的计算机有坏的RAM?

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

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

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

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

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

于 2012-10-15T13:15:03.430 回答
0

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

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

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

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

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

于 2014-10-31T15:34:44.350 回答