【问题标题】:ASP.NET: Should I be worried about memory leaks in certain situations? [C#]ASP.NET:在某些情况下我应该担心内存泄漏吗? [C#]
【发布时间】:2011-05-24 22:14:33
【问题描述】:

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

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 请求中创建多次,如果垃圾收集器无法清理它们,它们可能会一直持续到服务器重新启动。
可能的负面结果:

.NET 在这种场景下如何处理垃圾回收?

【问题讨论】:

  • 您认为这是个问题吗?我认为垃圾收集器应该能够检测到原始的A<->B 是一个岛引用,并且都可以安全地删除。
  • “通常情况下,垃圾收集器......” - 不,它没有。 :)

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


【解决方案1】:

.NET GC 通过跟踪根引用来工作,例如静态字段和范围内的局部变量。它正确处理参考周期。例如如果 A B,但都不是从根引用中引用的,则将其收集。

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

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

【讨论】:

    【解决方案2】:

    如果 A -> B, B -> A 并且没有其他对 A 和 B 的引用,则 GC 足够聪明地释放这些对象。

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

    【讨论】:

      【解决方案3】:

      .NET 垃圾收集器可以毫无问题地清理循环引用。

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

      【讨论】:

        【解决方案4】:

        更简单地说:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-08
          • 1970-01-01
          • 2012-07-18
          • 1970-01-01
          • 2014-06-10
          • 1970-01-01
          相关资源
          最近更新 更多