如何检测内存泄漏

发布于 2025-01-04 20:34:50 字数 2703 浏览 0 评论 0原文

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

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

I have doubts that this part of code causes memory leak:

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

How could I make a test to see if this piece of code is the cause?

EDIT:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我一直都在从未离去 2025-01-11 20:34:51

我会把它写成

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 & bitmap.Dispose 被调用。

I would write it as

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

to ensure that stream.Dispose & bitmap.Dispose are called.

半枫 2025-01-11 20:34:51

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

Might want to call stream.dispose(); after Byte[] bytes = stream.ToArray();.

别理我 2025-01-11 20:34:51

考虑到问题是如何检测内存泄漏/使用情况,我建议编写一个方法来调用您的函数,记录之前和之后的内存使用情况:

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 变量将保存您的函数在垃圾收集器运行之前使用了多少内存,而 unreclaimed 将告诉您即使在尝试清理对象之后,您的函数也使用了多少字节。

我怀疑已使用的值会很高,而未回收的值不会很高 - 正如其他海报所建议的那样,在内存流周围放置一个 using 应该会使它们更接近,但请记住,您仍然有一个字节数组保存在内存中。

Given the question was how to detect memory leaks/usage, I'd recommend writing a method that calls your function recording the memory usage before and after:

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 will measure the memory usage before your function runs. The used variable will hold how much memory your function used before the garbage collector was run and unreclaimed will tell you how many bytes your function used even after trying to clean up your objects.

I suspect used will be high and unreclaimed will not - putting a using around your memory stream as the other posters suggest should make them closer although bear in mind you still have a byte array holding on to memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文