ASP.NET:在某些情况下我应该担心内存泄漏吗? [C#]

时间:2010-12-13 21:07:49

标签: c# .net asp.net memory-leaks garbage-collection

在两个对象相互引用的情况下,我担心垃圾收集...

public class A
{   public readonly B _b;
    public A()
    {   _b = new B(this);
    }
}

public class B
{   public readonly A _a;
    public B(A objA)
    {   _a = objA;
    }
}

在这种情况下,第三类可以引用A ...

public class Foo
{   public A _a = new A(); // A and B are both created here.
    public void Bar()
    {   _a = new A();
    }   // Create a new A (and B)
}

通常,垃圾收集器会处理不再具有任何活动引用的对象。但在这种情况下,A和B对象永远不会丢失所有活动引用,因为它们总是引用彼此。

Foo对象用新A(和B)替换当前A(和B)时,垃圾收集器是否能够清除旧A(和B)而不用圆形对象引用开始无限循环?

这是一个严重的问题,因为它是一个ASP.NET应用程序。这些对象将在每个Web请求中多次创建,并且如果垃圾收集器无法清除它们,则可能会在服务器重新启动之前停留。 可能的负面结果:
<<由于RAM溢出,Web服务器崩溃 <<由于无限垃圾收集循环,Web服务器崩溃。

在这种情况下,.NET如何处理垃圾收集?

4 个答案:

答案 0 :(得分:7)

.NET GC通过跟踪有根引用(例如静态字段和范围内局部变量)来工作。它正确处理参考周期。例如如果A< - > B,但都没有从带有引用的引用引用,它被收集。

  

让我们考虑GC如何确定   什么时候它可以回收记忆。当。。。的时候   CLR尝试分配内存和   它没有足够的记忆储备   执行垃圾收集。 GC   枚举所有有根引用,   包括静态字段和范围内   任何线程调用的局部变量   堆。它将这些引用标记为   可达,并遵循任何参考   这些对象包含,标记为   也可以到达。它继续这样做   过程直到它访问了所有   可达参考。任何没有标记的   对象无法访问,因此   是垃圾。 GC压缩了   托管堆,整理引用   指向他们在新的位置   堆,并将控制权返回给CLR。   如果释放了足够的内存,   分配继续使用此   释放记忆。如果没有,额外的   操作请求内存   系统

- 来自http://msdn.microsoft.com/en-us/magazine/cc163491.aspx

答案 1 :(得分:2)

如果A - >; B,B - > A并且没有其他对A和B的引用,GC足够智能以释放这些对象。

在ASP.NET中,增加了应用程序池的保险。应用程序的许多实例保存在内存中,并根据需要分配给各种会话。有时,即使在会话的上下文中,IIS也会决定刷新应用程序池的好时机。当会话结束时,IIS通常会关闭并重新启动应用程序,如果它与每个应用程序,每个池或整个系统内存限制相冲突。有时这甚至发生在会话中间;这在SOA中是常见的,其中外部Web层通过WCF与另一个服务器通信,并且服务层可以在Web层的调用之间刷新。

答案 2 :(得分:1)

.NET Garbage收集器可以毫无问题地清除循环引用。

它不计算对旧VB6 GC等对象的引用 它通过从特殊的“对象根”开始遍历内存中的所有对象来跟踪活动对象。

答案 3 :(得分:1)

更简单地说:

当垃圾收集器运行时,它从内存寄存器和静态字段等开始。这些被称为“根”。

从那里,垃圾收集器跟踪从根到其他对象实例的引用。这将创建一个从根可以到达的所有对象的图形。

如果您的对象无法从根目录访问,那么它们将被视为未引用,并且可以被垃圾收集器清理。