【发布时间】:2014-10-06 02:44:11
【问题描述】:
我注意到我的程序正在泄漏内存。于是我用 dotMemory 查找泄漏,看起来这是导致泄漏的函数:
private void LoadBits()
{
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bm.Width, bm.Height);
bmpData = bm.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bm.PixelFormat);
stride = bmpData.Stride;
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
byteCount = Math.Abs(bmpData.Stride) * bm.Height;
bytes = new byte[byteCount];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, byteCount);
}
这就是我解锁这些位的方式。
private void SaveBits()
{
// Update Stuff
IntPtr ptr = bmpData.Scan0;
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, ptr, byteCount);
bm.UnlockBits(bmpData);
}
我为这个类实现了 IDisposable 接口。我在那里调用 SaveBits,所以即使我忘记调用 SaveBits,GC 也应该为我做这件事。 是的,我确实调用了 bm.Dispose() 并在 Dispose 方法中将所有内容设置为 null。
【问题讨论】:
-
LoadBits 和 SaveBits 使用不同的变量。一个是
_bm,另一个是bm,你能在错误的对象上解锁位吗?也可以在调用SaveBits()之前多次调用LoadBits(),这也会导致内存泄漏。尝试将bmpData = null放在SaveBits()的末尾,并将if (bmpData != null) throw new InvalidOperationException();放在LoadBits()的开头,看看是否会抛出异常。 -
我在发布问题后进行了重构。所以“LoadBits”显示的是旧的 var 名称。请允许我更新它。
-
如果做空检查,抛出异常,不抛出吗?
-
我无法加载两次。 Bitmap 类抛出异常,表示内存已被锁定。根据您的建议修改代码并执行 null 检查会导致抛出异常。
-
好吧,如果它导致你发现你的问题,在调用
SaveBits清除它之前,有东西正在写入 bmpData。您正在失去锁定位的句柄,这就是您的内存韭菜的原因。
标签: c# memory memory-leaks