如何检测内存泄漏

时间:2012-02-13 23:26:36

标签: c# asp.net memory-leaks memorystream

我怀疑这部分代码会导致内存泄漏:

    public FileResult ShowCroppedImage(int id, int size)
    {
        string path = "~/Uploads/Photos/";
        string sourceFile = Server.MapPath(path) + id + ".jpg";

        MemoryStream stream = new MemoryStream();
        var bitmap = imageManipulation.CropImage(sourceFile, size, size);
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        Byte[] bytes = stream.ToArray();
        return File(bytes, "image/png");
    }

我如何进行测试以确定这段代码是否是原因?

编辑:

public Image CropImage(string sourceFile, int newWidth, int newHeight)
        {
            Image img = Image.FromFile(sourceFile); 
            Image outimage;

            int sizeX = newWidth;
            int sizeY = newHeight;

            MemoryStream mm = null;

            double ratio = 0;
            int fromX = 0;
            int fromY = 0;

            if (img.Width < img.Height)
            {
                ratio = img.Width / (double)img.Height;
                newHeight = (int)(newHeight / ratio);
                fromY = (img.Height - img.Width) / 2;
            }
            else
            {
                ratio = img.Height / (double)img.Width;
                newWidth = (int)(newWidth / ratio);
                fromX = (img.Width - img.Height) / 2;
            }
            if (img.Width == img.Height)
                fromX = 0;

            Bitmap result = new Bitmap(sizeX, sizeY);

            //use a graphics object to draw the resized image into the bitmap 
            Graphics grPhoto = Graphics.FromImage(result);

            //set the resize quality modes to high quality 
            grPhoto.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            grPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //draw the image into the target bitmap 
            //now do the crop            
            grPhoto.DrawImage(
                img,
                new System.Drawing.Rectangle(0, 0, newWidth, newHeight),
                new System.Drawing.Rectangle(fromX, fromY, img.Width, img.Height),
                System.Drawing.GraphicsUnit.Pixel);


            // Save out to memory and get an image from it to send back out the method.
            mm = new MemoryStream();
            result.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
            img.Dispose();
            result.Dispose();
            grPhoto.Dispose();
            outimage = Image.FromStream(mm);

            return outimage;
        }

3 个答案:

答案 0 :(得分:3)

我会把它写成

public FileResult ShowCroppedImage(int id, int size)
{
    string path = "~/Uploads/Photos/";
    string sourceFile = Server.MapPath(path) + id + ".jpg";

    using (MemoryStream stream = new MemoryStream())
    {
        using (Bitmap bitmap = imageManipulation.CropImage(sourceFile, size, size))
        {
            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            Byte[] bytes = stream.ToArray();
            return File(bytes, "image/png");
        }
    }
}

确保stream.Dispose&amp;调用bitmap.Dispose。

答案 1 :(得分:0)

可能希望在stream.dispose();之后致电Byte[] bytes = stream.ToArray();

答案 2 :(得分:0)

鉴于问题是如何检测内存泄漏/使用情况,我建议编写一种方法来调用函数来记录前后的内存使用情况:

public void SomeTestMethod()
{
    var before = System.GC.GetTotalMemory(false);
    // call your method
    var used = before - System.GC.GetTotalMemory(false);
    var unreclaimed = before - System.GC.GetTotalMemory(true);
}

之前将测量函数运行前的内存使用情况。 used变量将保存函数在运行垃圾收集器之前使用了多少内存,而未收回的函数将告诉您函数在尝试清理对象后使用了多少字节。

我怀疑使用率会很高而且无法回收也不会 - 在你的内存流中使用,因为其他海报建议应该让它们更接近,但请记住,你仍然有一个字节数组保留在内存中。