在这篇文章中:Possible memory leak in Zxing's System.Drawing.Bitmap询问有关ZXing库中内存泄漏的问题。我已经下载并修改了库,没有分配的内存。我甚至在适用的情况下引入了using(){}语句,但我仍然遇到内存泄漏。
我怀疑。 Marshal.Copy可能会做更多,然后只是将数据从源复制到目标。我可能还必须在复制后释放目的地吗?
正如您在下面的代码中所看到的,我甚至尝试仅分配缓冲区一次,并且只在请求大于前一个图像的图像时重新分配缓冲区,但这并没有解决问题。
此致 保罗
我改变了代码:
using System;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace System.Drawing
{
public class Bitmap : IDisposable
{
byte[] pixelData = new byte[0];
int width = 0;
int height = 0;
static IntPtr m_BufferPointer = default(IntPtr);
static int m_Size;
/// <summary>
/// Reallocs the buffer when it becomes too small
/// </summary>
private IntPtr ReallocBuffer(int size)
{
if(m_BufferPointer != default(IntPtr))
{
if(m_Size < size)
{
Marshal.FreeHGlobal(m_BufferPointer);
m_BufferPointer = Marshal.AllocHGlobal(size);
}
}
else
{
m_BufferPointer = Marshal.AllocHGlobal(size);
}
m_Size = size;
return m_BufferPointer;
}
public Bitmap (UIImage image)
{
UIImage backingImage = image;
IntPtr rawData;
using (CGImage imageRef = backingImage.CGImage)
{
width = imageRef.Width;
height = imageRef.Height;
using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB ())
{
int size = height * width * 4;
rawData = ReallocBuffer(size); //Marshal.AllocHGlobal (height * width * 4);
using (CGContext context = new CGBitmapContext (rawData, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast))
{
context.DrawImage (new RectangleF (0.0f, 0.0f, (float)width, (float)height), imageRef);
pixelData = new byte[height * width * 4];
Marshal.Copy (rawData, pixelData, 0, pixelData.Length);
}
}
}
}
private static int CountCalled;
private static int LastCountCalled = 20000000; //30411000;
public Color GetPixel (int x, int y)
{
try
{
CountCalled++;
if (CountCalled - LastCountCalled > 100000)
{
Debug.WriteLine (CountCalled);
LastCountCalled += 1000000;
}
byte bytesPerPixel = 4;
int bytesPerRow = width * bytesPerPixel;
int rowOffset = y * bytesPerRow;
int colOffset = x * bytesPerPixel;
int pixelDataLoc = rowOffset + colOffset;
Color ret = Color.FromArgb (pixelData [pixelDataLoc + 3], pixelData [pixelDataLoc + 0], pixelData [pixelDataLoc + 1], pixelData [pixelDataLoc + 2]);
return ret;
}
catch (Exception ex)
{
Console.WriteLine ("Req: {0}x{1}", x, y);
throw ex;
}
}
#region IDisposable implementation
public void Dispose ()
{
pixelData = null;
GC.Collect(0);
}
#endregion
}
}
答案 0 :(得分:2)
您需要释放本机缓冲区,CGBitmapContext将不会为您执行此操作:
IntPtr rawData = Marshal.AllocHGlobal (height * width * 4);
try {
using (CGContext context = new CGBitmapContext (rawData, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast))
{
context.DrawImage (new RectangleF (0.0f, 0.0f, (float)width, (float)height), imageRef);
pixelData = new byte[height * width * 4];
Marshal.Copy (rawData, pixelData, 0, pixelData.Length);
}
} finally {
Marshal.FreeHGlobal (rawData);
}
根据Jonathan.Peppers在评论中尝试最终建议更新