2011-06-28 111 views
7

我的应用程序图形引擎抛出这些异常。它们全部被空的捕获块消耗掉。在早期,我发现了一个没有被困住的东西(与我记得的笔相关联)。我用尝试和一个空的抓块包围它。看起来这些例外对所制作的图纸没有影响。我在这方面做了一些阅读,但没有真正理解或深入到底。System.Drawing内存不足异常

所以我的问题:

  1. 为什么他们是否可以安全食用这些被抛出?和
  2. 忽视它们是否安全?我担心每个人都有一些隐藏的效果。我有内存泄漏,我从来没有找到例如。
+0

在使用它们之后,你是否在处理像笔,画笔,图形,图像等东西? –

+4

他们会抛出告诉您,您的代码已损坏。用一个空的catch子句捕捉它们并不能修复你的代码,它只是射击信使。 –

+1

当GDI +实际上是一个无效参数时,它有时会抛出一个内存不足的异常。不知道这是否与此有关。 – CodesInChaos

回答

19

我看过System.Drawing抛出OutOfMemoryExceptions,即使它没有内存不足。某些GDI +函​​数显然只是返回一个愚蠢的错误代码。

IIRC,如果您尝试使用LinearGradientBrush填充宽度或高度为零的矩形,将会发生OutOfMemoryException。也可能有其他条件,但这是我们遇到的主要问题。

在这种情况下,不需要try/catch。只需在图形代码中添加if语句,并且如果宽度或高度为零,则不要填充矩形。

更新:根据关于this answer的意见,它也可能发生如果您尝试加载损坏的图像文件。为此,你别无选择,只能做try/catch。

您可能会安全地捕获GDI +中的OutOfMemoryExceptions,但请尽量保持try块不变。考虑记录例外情况,以便您可以分析日志并在可能的情况下添加防御性代码。你不想掩盖真实 OutOfMemoryException,但你不希望一个愚蠢的GDI +错误代码崩溃你的应用程序。

+0

它没有涉及它正在绘制的图像文件。使用日志的好主意。该应用程序有一个记录器,所以我会添加一些记录到catch子句并查看显示的内容。如果看起来很讨厌,我会添加一些防御性代码。 – ScruffyDuck

+0

2016年谢谢!你救了我的一天! – Genius

+0

如果您需要绘制垂直或水平的渐变线,该怎么办?然后矩形的宽度或高度为零! – AaronF

2

这是一个非常糟糕的例外:http://msdn.microsoft.com/en-us/library/system.outofmemoryexception.aspx .. 没有足够的内存来继续程序的执行。

你会经常发现,如果你分配了这么多“简单”的操作/分配会引发这个消息,那么应用程序很快就会崩溃。如果这是一个失败的大规模分配,您可能会继续。

如果应用程序执行任何重要操作,则应该尝试优雅地关闭所有内容。

要明确地回答你的问题:

  1. 他们抛出这样的应用程序有机会作出反应/恢复:一些内存分配(10GB值得对象)可以预料在许多情况下失败,也许是一个在线应用程序崩溃(int[] x = new int[5368709120];当量)确实应该抛出一个异常,而不是崩溃一切

  2. 应该没有隐藏的效果,但如果分配失败,你要那么也许下一次string或其他有用对象以一些小的方式分配给一般操作的应用程序:事情可能会变得不稳定。这就是说根据环境的不同,你可能会在任何时候得到这个异常..

编辑:任何人阅读这也应该考虑,显然GDI +引发此异常其他原因了。

+0

感谢 - 说实话,我们从未让应用程序崩溃。我们有大约30,000个用户,并且这还没有被报道。但是,如果我查看VS中的输出日志,我会看到几十个这种类型的“第一次机会异常”被空的catch子句使用。 – ScruffyDuck

+2

当GDI +抛出它时,OOM意味着其他东西。 GDI +异常相当草率。 –

+0

通常情况是这样,但即使内存不足,GDI +也会抛出OutOfMemoryException。我已经看到了它。某些函数返回一个错误的错误代码或其他东西。 –

0

我试过解决方案'乔怀特'建议,就是这样。 它抛出了OutOfMemoryException,因为矩形的宽度和高度都是0.在我的例子中,发生异常时窗口被最小化了。

这里是一个例子;

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 

    Using e 
     ##Add conditions to avoid OutOfMemoryException## 
     If (Not ClientRectangle.Width = 0) And (Not ClientRectangle.Height = 0) Then 
      Using rect As GraphicsPath = New GraphicsPath() 
       rect.AddRectangle(ClientRectangle) 

       Using gb As New PathGradientBrush(rect) 
        gb.WrapMode = WrapMode.Tile 
        gb.SurroundColors = New Color() {GradientColors(1), GradientColors(0), GradientColors(2)} 
        gb.CenterColor = GradientColors(0) 
        gb.SetSigmaBellShape(0.5F) 
        e.Graphics.FillPath(gb, rect) 
       End Using 
      End Using 
     End If 
    End Using 

End Sub