如何检测内存泄漏

本文关键字:内存 泄漏 检测 何检测 | 更新日期: 2023-09-27 18:24:42

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

    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;
        }

如何检测内存泄漏

我会把它写成

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");
        }
    }
}

以确保该流。处置&位图。调用Dispose。

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

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

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);
}

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

我怀疑used会很高,而un-requested不会——像其他海报所建议的那样,在你的内存流中使用应该会让它们更接近,尽管要记住,你仍然有一个字节数组保存着内存。