【问题标题】:C# Memory leak with BitmapC# 内存泄漏与位图
【发布时间】:2015-03-04 02:01:14
【问题描述】:

我正在用 C# 编写一个基于图块的游戏。但是我遇到了一个问题,当应用程序处于窗口模式时,我的系统内存会振荡大约 +-300MB,并且在全屏模式下它会耗尽所有内存并抛出 OutOfMemoryException。

据我所知,我找不到任何忘记 .Dispose() 可能导致此问题的地方。

我能查明问题的最接近的地方是我将.Clone() 位图转换为 PictureBox.Image 的地方。这种情况每帧发生一次。我在内存中渲染了整个“世界”,这是一个大约 2000x1000 像素的位图,我从中复制要在屏幕上显示的部分。

我可以附上代码,但因为它很多,我会等到问题明显存在,而不是上面的方法。

谢谢

编辑:这就是我认为问题所在:

public Bitmap GetMap(Rectangle renderedArea)
    {
        if (renderedArea.Bottom > renderedMap.Height || renderedArea.Right > renderedMap.Width)
            return renderedMap.Clone(new Rectangle(0,0,renderedMap.Width,renderedMap.Height),renderedMap.PixelFormat);
        return renderedMap.Clone(renderedArea, renderedMap.PixelFormat);
    }

public void Render(Rectangle area)
    {      
        renderArea.Image = worldEditor.map.GetMap(area);
        Graphics g = Graphics.FromImage(renderArea.Image);

        PointF stringPoint = MouseInputEventHandler.CursorLocation.ToCoords(worldEditor.map.TileArray.TileSize,worldEditor.RENDER_START);
        g.DrawString(string.Format("{0},{1}", (int)stringPoint.X, (int)stringPoint.Y), new Font("Arial",15,FontStyle.Bold), Brushes.Yellow, new PointF(6, 6));
        g.Dispose();
    }

通过查看相关问题(谷歌没有向我展示!)我发现将其添加到 Render() 函数可以解决问题:

if (renderArea.Image != null)
            renderArea.Image.Dispose();

不过,我很想知道为什么还要处理掉它。

【问题讨论】:

  • 没有代码,将很难帮助...
  • 为什么这被否决了?很清楚他在问什么。
  • @MillieSmith 在添加代码之前可能已经投下反对票
  • @BradleyDotNET 我不认为是这样,因为当我点击问题时,代码已经添加并且没有投票。
  • @MillieSmith 那么没有线索,这是一个很好的问题

标签: c# memory-leaks bitmap


【解决方案1】:

当您Clone 时,您会创建对象的副本。所以你的newBitmap 对象最终也需要调用Dispose

renderArea.Image = worldEditor.map.GetMap(area);

重新分配图像而不进行处理,因此您泄漏了旧对象。如果您将帖子中的代码添加到其中,则可以清理对象,从而解决您的问题。

一种可能更清晰的书写方式是:

Bitmap oldImage = renderArea.Image;
renderArea.Image = worldEditor.map.GetMap(area);

if (oldImage != null)
    oldImage.Dispose();

【讨论】:

  • 谢谢。我的印象是旧图像会被新图像覆盖,这显然是错误的。
  • @user2790895 是的,引用不能那样工作:)
  • 是的,我知道引用,但我的意思是当新图像出现时,旧图像将不再被引用,因此它不应该被 GarbageCollected 吗?
  • @user2790895 可以,但是Bitmap包装了一个GDI位图,需要手动dispose才能及时释放海量的非托管对象。
  • 无论如何,位图都应该由 GC 处理(在终结器中)。
猜你喜欢
  • 2013-10-01
  • 2016-03-14
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2013-06-05
  • 2015-06-28
  • 1970-01-01
相关资源
最近更新 更多