我遇到了一些奇怪的 OutOfMemory 异常。
我们有一个应用程序,它基本上为来自某些硬件设备的数据绘制了一些图表。
如果我使用 MemoryProfiler 运行应用程序,一段时间后,我得到了一些OutOfMemoryException
. 我们知道,即使没有调试器,我们的一些客户也会发生同样的异常。
奇怪的部分:
- 我们还有足够的可用内存空间
- 出现此异常时,应用程序仅使用 360MB
我们正在使用 Nevron 库来绘制图表,我们得到的异常是:
System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
at Nevron.GraphicsCore.NBitmapGdiRenderSurface.Paint(Object sender, PaintEventArgs e, l1ll11Il1 contentPainter)
at Nevron.Chart.WinForm.NControlView.Paint(Object sender, PaintEventArgs e)
at Nevron.Chart.WinForm.NChartControl.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.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)
我们将 DevExpress 用于应用程序的所有其他部分。我们也设法从他们那里得到了这个错误(我不确定他们是否相关,但我有他们的感觉):
System.ComponentModel.Win32Exception (0x80004005): Not enough storage is available to process this command
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height)
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.Allocate(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
at DevExpress.Utils.Drawing.XtraBufferedGraphicsContext.Allocate(Graphics targetGraphics, Rectangle targetRectangle)
at DevExpress.XtraBars.Docking2010.Views.BaseViewPainter.Draw(GraphicsCache cache, Rectangle clip)
at DevExpress.XtraBars.Docking2010.Views.BaseView.Draw(GraphicsCache cache, Rectangle clip)
at DevExpress.XtraBars.Docking2010.DocumentManager.PaintCore(Graphics g, Rectangle bounds)
at DevExpress.XtraBars.Docking2010.DocumentManager.DevExpress.XtraBars.Docking2010.IDocumentsHostOwner.Paint(Graphics g)
at DevExpress.XtraBars.Docking2010.DocumentsHost.OnPaint(Graphics g)
at DevExpress.XtraBars.Docking2010.DocumentsHost.DoPaint(Message& m)
at DevExpress.XtraBars.Docking2010.DocumentsHost.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)
我们有一个“捕获所有异常”处理程序,允许应用程序在异常发生后不关闭。目前这是对 GUI 的影响(它所在的位置取决于异常发生的位置:
这是崩溃时的 GDIView 情况(计数器一直在增加/减少,幅度不大,但通常,当 GC 运行时,我会回到 0 偏移量。):
我已经检查过的内容:
- ANTS 探查器不会警告我在此异常之前和之后拍摄的快照上的 LOH 碎片
- 我没有看到大的内存增加(内存泄漏)
- 我还有很多空间
- 我没有大量使用 GDI 句柄(使用GDIView检查)
我有点绝望,因为这个异常发生在我们的客户身上,在我的电脑上(我可以重现它,但不容易),但我不明白这里出了什么问题,我在互联网上发现的一切都是关于拥有 GDI句柄增长(或让另一个应用程序的 GDI 句柄增长),但似乎并非如此。
这个错误似乎总是发生在直接与 GUI 接触的东西上,即使当我们接收到数据时,我们也必须分配大数组(不是那么大,但经常)。
我该怎么做才能获得有关此异常的更多信息?
我已经发现的东西:
- TestLimit允许我创建超过 1600 万个新句柄
- 这个 SO question,但在这里我找不到增加句柄的线索
- 这篇文章,但我检查了,我所有的新文章
Graphic
都被处理掉了(不知道图书馆的那些 - LOH上的这篇文章,但是根据ANTS的说法,这似乎不是我的问题
我向 Nevron/DevExpress 报告了这个问题,但不确定他们是否能提供帮助,目前没有答案。
编辑
我确实设法让蚂蚁告诉我这个:
但是,我不确定我是否应该考虑它,因为不可用的空间非常低,而且我还有足够的内存空间(LOH 有大小限制吗?)