垃圾收集器没有做它的工作。内存消耗= 1.5GB& OutOFMemory例外

时间:2010-04-01 10:54:48

标签: c# .net

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace TrainSVM
{
    class Program
    {
        static void Main(string[] args)
        {
            FileStream fs = new FileStream("dg.train",FileMode.OpenOrCreate,FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            String[] filePathArr = Directory.GetFiles("E:\\images\\");

            foreach (string filePath in filePathArr)
            {
                if (filePath.Contains("HBP"))
                {
                    sw.Write("1 ");
                    Console.Write("1 ");
                }
                else
                {
                    sw.Write("1 ");
                    Console.Write("1 ");
                }

                using (Bitmap originalBMP = new Bitmap(filePath))
                {


                    /***********************/
                    Bitmap imageBody;
                    ImageBody.ImageBody im = new ImageBody.ImageBody(originalBMP);
                    using (imageBody = im.GetImageBody(-1))
                    {

                        /* white coat */
                        Bitmap whiteCoatBitmap = Rgb2Hsi.Rgb2Hsi.GetHuePlane(imageBody);
                        float WhiteCoatPixelPercentage = Rgb2Hsi.Rgb2Hsi.GetWhiteCoatPixelPercentage(whiteCoatBitmap);
                        //Console.Write("whiteDone\t");
                        sw.Write("1:" + WhiteCoatPixelPercentage + " ");
                        Console.Write("1:" + WhiteCoatPixelPercentage + " ");

                        /******************/
                        Quaternion.Quaternion qtr = new Quaternion.Quaternion(-15);
                        Bitmap yellowCoatBMP = qtr.processImage(imageBody);
                        //yellowCoatBMP.Save("yellowCoat.bmp");
                        float yellowCoatPixelPercentage = qtr.GetYellowCoatPixelPercentage(yellowCoatBMP);
                        //Console.Write("yellowCoatDone\t");
                        sw.Write("2:" + yellowCoatPixelPercentage + " ");
                        Console.Write("2:" + yellowCoatPixelPercentage + " ");

                        /**********************/
                        Bitmap balckPatchBitmap = BlackPatchDetection.BlackPatchDetector.MarkBlackPatches(imageBody);
                        float BlackPatchPixelPercentage = BlackPatchDetection.BlackPatchDetector.BlackPatchPercentage;
                        //Console.Write("balckPatchDone\n");
                        sw.Write("3:" + BlackPatchPixelPercentage + "\n");
                        Console.Write("3:" + BlackPatchPixelPercentage + "\n");
                    }
                }


                sw.Flush();

            }


            sw.Dispose();
            fs.Dispose();

        }

    }
}

8 个答案:

答案 0 :(得分:10)

那里有一些你没有处理的Bitmap实例。你应该尝试养成使用using块而不是手动处理的习惯,以阻止这些东西在网上滑落。

答案 1 :(得分:5)

如果你在这一行得到例外:

using (Bitmap originalBMP = new Bitmap(filePath))

那么这可能意味着您正在尝试加载无效或损坏的图像文件。由于没有人知道的原因,OutOfMemoryException是在这种情况下抛出的。它实际上与内存不足无关。

尝试使用google搜索“bitmap.fromfile outofmemoryexception”。

答案 2 :(得分:2)

你不应该处置imageBody吗?

我看到它打开了:

Bitmap imageBody; 
ImageBody.ImageBody im = new ImageBody.ImageBody(originalBMP); 
imageBody = im.GetImageBody(-1); 

但是我没有看到你处理它/将它设置为null?

答案 3 :(得分:2)

也许你被这个错误所困扰: https://connect.microsoft.com/VisualStudio/feedback/details/521147/large-object-heap-fragmentation-causes-outofmemoryexception

在这种情况下,添加

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    GC.WaitForPendingFinalizers();
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
循环中的

可能有所帮助。

或者使用sos.dll http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx查看泄漏内存的位置。

答案 4 :(得分:2)

你有很多对各种类的调用,ImageBody,Rgb2Hsi,BlackPatchDetection等

我认为这些是你自己的代码。其中任何一个都可以持有资源。

我建议你抓一个探查器并进行一些测试。

他们中的大多数都有试用版,给你几天的时间。

Best .NET memory and performance profiler?

答案 5 :(得分:1)

尝试在使用()

中取Bitmap originalBMP = new Bitmap(filePath);
using (Bitmap originalBMP = new Bitmap(filePath)) {
  // your code....   
  sw.Flush();   
}

在离开该子句之后,在using()子句中的所有内容都被明确地处理掉。 您可以在处置它们之后将变量设置为null。

答案 6 :(得分:1)

您应该尽可能使用using语句而不是Dispose()。这样,您可以立即在声明中看到您刚创建的这个实例已被释放。

哪个更好?

Bitmap bmp = new Bitmap(filePath);
// .. pages of code goes here ..
bmp.Dispose(); // hopefully not forgotten

using (Bitmap bmp = new Bitmap(filePath))
{
// .. pages of code goes here ..
}

using语句还确保即使您使用return,break或甚至异常过早地保留当前块/方法,也会释放所有实例。

请注意,您可以将多个赋值放入using语句的开头!

答案 7 :(得分:0)

与任何垃圾收集问题一样,我的方法是开始评论事情,看看我是否还能重现内存泄漏。要尝试的事情:

  1. 在循环中仅实例化Bitmap的一个实例,以查看内存使用情况是否发生变化。
  2. Dispose / not Dispose一个Bitmap实例,看看处理是否有所不同。
  3. 根据我在最新版本的代码中看到的内容,whiteCoatBitmapyellowCoatBitmapblackPatchBitmap未被处置。围绕那些使用块的人。