2012-06-11 59 views
4

我是一名新程序员,我只想出一个内存泄漏的问题。如果我在一个循环中声明一个变量以使其一次又一次被声明,我是否在泄漏内存? 例如,我有我在循环中泄漏内存吗?

while(true) 
{ 
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768); 
    //do something else 
} 

我知道这是一个无限循环,但我的问题是关于内存。内存使用量在这个循环中增长得快吗?我应该手动释放MyImage吗?

+0

我会冒险猜测,并说是...但我不是100%确定,所以请不要把它当作福音。 – Richard

+0

@Killercam你确定吗?因为我听到了不同的东西,我不知道。在这种情况下,或者一般来说,你的意思是说Image对象可以吗? – YankeeWhiskey

回答

6

使用后需要拨打MyImage.Dispose()

另一种方式是将代码更改为:

while(true) 
{ 
    using(Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)){ 
     //do something else 
    } 
} 
+0

我意识到也许这个班不实施'IDisposable'。所以,如果它实现了IDisposable,或者它使用了实现IDisposable的某些东西,那么应该采用它,在这种情况下,您应该实现它来处理内部对象。 – ivowiblo

+0

这只是为了提高效率还是真正的内存泄漏? – YankeeWhiskey

+0

类型为IDisposable的类通常使用在调用Dispose()方法之前不能释放的内存。正如你可能在无限循环中使用它们一样,它可能导致内存泄漏(我的意思是,如果你使用Disposable对象而不调用Dispose,它会导致内存泄漏) – ivowiblo

1

我是不是内存泄漏,如果我在一个循环中声明一个变量,使其一再声明?

不,你不这样做,如其他人所说的问题可能是,如果图像是包装的Image对象

但对于你的问题,这是不申报在一个循环内的变量的问题,在每次迭代中为其指定一个新值

1

有些情况下,紧密环路可能导致OOM问题。但是,Image实现了IDisposable,因此请务必通过using声明对其进行调用,以便在完成后可以释放资源。

using (Image<Gray, Byte> MyImage = new Image<Gray, Byte>(1024, 768)) 
{ 
    //do stuff 
} 

确保Image<T,U>工具IDisposable如果Image<T,U>实现所有管理对象。

1

在你的问题的一般形式中,你本身并没有泄漏内存,但是你可能会增加你的内存占用比GC更快的速度(取决于你正在使用的对象的确切行为和内存占用情况)。如果是这样,这将会产生很多类似于内存泄漏的效果。

在您的具体示例中,Image对象包含非托管资源,其中可能包括内存(或文件句柄或GDI对象等)。正如其他答案所指出的那样,如果你不处理,这些非托管资源将不会被回收(或者如果他们有终结器,则可以在GC的第二次回收中回收)。

3

垃圾收集器(GC)将为您完成这项工作 - 最终。在你提出的例子中,你必须小心,因为在这种情况下GC会尝试和管理它花费在垃圾收集上的时间与应用程序内存消耗(工作集)的时间。因此,应用程序可能会消耗更多的内存,尤其是在您说明的情况下。

CLR完全自动处理这个内存,你永远不会自己释放托管内存。例如,考虑下面的

public void Test() 
{ 
    byte[] myArray = new Byte[1000]; 
    // ... 
} 

Test执行时,一个数组来保存1000个字节是在存储器堆中分配。该数组由变量myArray引用,存储在局部变量堆栈中。当这个方法退出时,这个局部变量会超出范围,这意味着什么都没有留下来引用内存堆上的数组。然后,孤立数组有资格被GC回收。然而,这个集合可能不会立即发生,因为CLR关于是否收集的决定是基于许多因素(可用内存,当前内存分配,自上次收集以来的时间等)。t这意味着,对于收集是否存在不确定的延迟垃圾回收之前所花费的时间。

鉴于上述情况,在您描述的情况下,在循环/包含方法期间内存消耗会大幅增加。这里要好得多要么使用一个using声明

while (true) 
{ 
    using (Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)) 
    { 
     // ... 
    } 
} 

或每个循环之后的Image调用对象的dispose()

while (true) 
{ 
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768); 
    // ... 
    MyImage.Dispose(); 
} 

Asside:你可以随时检查这些内存消耗为自己(使用System.Diagnostics程序)通过查询性能计数器(测试你的流程的实际内存消耗):

string procName = Process.GetCurrentProcess().ProcessName; 
using (PerformanceCounter pc = new PerformanceCounter("Process", "Private Bytes", procName)) 
    Console.WriteLine(pc.NextValue()); 

注:读取性能计数器需要管理员权限。