我是在循环中泄漏记忆吗?

时间:2012-06-11 15:39:59

标签: c# loops memory-leaks

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

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

我知道这是一个无限循环,但我的问题是关于记忆。此循环中的内存使用量是否快速增长?我应该手动发布MyImage吗?

5 个答案:

答案 0 :(得分:6)

使用后需要致电MyImage.Dispose()

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

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

答案 1 :(得分: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))
    {
        // ...
    }
}

或在每次循环后在dispose()对象上调用Image

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

注意:阅读效果计数器需要管理员权限。

答案 2 :(得分:1)

  

如果我在循环中声明一个变量以便一次又一次地声明它,我是否会泄漏内存?

不,你没有,其他人提到的问题可能是Image正在包装一个Image对象

但是对于你的问题,在循环中声明一个变量并在每次迭代时为它赋予一个新值不是问题

答案 3 :(得分: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>

答案 4 :(得分:1)

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

在您的特定示例中,Image对象包含非托管资源,可能包括内存(或文件句柄或GDI对象等)。正如其他答案所指出的那样,如果您不进行处置,那么这些非托管资源将无法回收(或者如果他们有终结器,可以在GC的第二遍中回收)。