简体   繁体   English

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

[英]ASP.NET: Should I be worried about memory leaks in certain situations? [C#]

I'm concerned about garbage collection in the case where two objects reference each-other ... 在两个对象相互引用的情况下,我关注垃圾收集......

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;
    }
}

In this case, a third class may reference A ... 在这种情况下,第三类可以引用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)
}

Normally, the Garbage Collector disposes of objects that no longer have any active references. 通常,垃圾收集器会处理不再具有任何活动引用的对象。 But in this case, A and B objects never lose all of their active references, since they always reference each-other. 但在这种情况下,A和B对象永远不会丢失所有活动引用,因为它们总是相互引用。

When the Foo object replaces the current A (and B ) with a new A (and B ), Will the Garbage Collector be able to clean up the old A (and B ) without starting an infinite loop with the circular object references? Foo对象用新的A (和B )替换当前的A (和B )时,垃圾收集器是否能够清除旧的A (和B )而不用循环对象引用启动无限循环?

This is a serious concern because it is an ASP.NET application. 这是一个严重的问题,因为它是一个ASP.NET应用程序。 These objects will be created numerous times per web request, and may linger until the server is restarted if the Garbage Collector can't clean them up. 这些对象将在每个Web请求中多次创建,并且如果垃圾收集器无法清除它们,则可能会延迟服务器重新启动。
Possible negative results: 可能的负面结果:
<< Webserver crashes due to RAM overflow. <<由于RAM溢出,Web服务器崩溃。
<< Webserver crashes due to infinite Garbage Collection loop. << Webserver因无限垃圾收集循环而崩溃。

How does .NET handle Garbage Collection in this type of scenario? 在这种情况下,.NET如何处理垃圾收集?

The .NET GC works by tracing rooted references, such as static fields and in-scope local variables. .NET GC通过跟踪有根引用来工作,例如静态字段和范围内局部变量。 It handles reference cycles properly. 它正确处理参考周期。 eg If A <--> B, but neither is referenced from a rooted reference, it is collected. 例如,如果A < - > B,但都没有从有根参考引用,则会收集它。

Let's consider how the GC determines when it can reclaim memory. 让我们考虑GC如何确定它何时可以回收内存。 When the CLR attempts to allocate memory and has insufficient memory in reserve, it performs a garbage collection. 当CLR尝试分配内存并且内存不足时,它会执行垃圾回收。 The GC enumerates all rooted references, including static fields and in-scope local variables on any thread's call stack. GC枚举所有有根引用,包括任何线程调用堆栈上的静态字段和范围内局部变量。 It marks these references as reachable and follows any references these objects contain, marking them as reachable as well. 它将这些引用标记为可访问,并遵循这些对象包含的任何引用,并将它们标记为可访问。 It continues this process until it has visited all reachable references. 它继续此过程,直到它访问了所有可访问的引用。 Any unmarked objects are not reachable and hence are garbage. 任何未标记的对象都是不可访问的,因此是垃圾。 The GC compacts the managed heap, tidies up references to point to their new location in the heap, and returns control to the CLR. GC压缩托管堆,整理引用以指向它们在堆中的新位置,并将控制权返回给CLR。 If sufficient memory has been freed, the allocation proceeds using this freed memory. 如果释放了足够的内存,则使用此释放的内存继续分配。 If not, additional memory is requested from the operating system. 如果不是,则从操作系统请求额外的内存。

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

If A -> B, B -> A and there is no other reference to A and B, the GC is smart enough to free these objects. 如果A - > B,B - > A并且没有对A和B的其他引用,则GC足够智能以释放这些对象。

In ASP.NET, there is the added insurance of an app pool. 在ASP.NET中,增加了应用程序池的保险。 Numerous instances of the application are kept in memory and are assigned to various sessions as needed. 应用程序的许多实例保存在内存中,并根据需要分配给各种会话。 From time to time, even within the context of the session, IIS will decide it's a good time to refresh the app pool. 有时,即使在会话的上下文中,IIS也会决定刷新应用程序池的好时机。 When the session ends, IIS will usually close and restart the app if it's bumping up against a per-application, per-pool or overall system memory limit. 当会话结束时,IIS通常会关闭并重新启动应用程序,如果它与每个应用程序,每个池或整个系统内存限制相冲突。 Sometimes this even happens in the middle of a session; 有时这甚至发生在会话中间; this is common in SOAs where an exterior web layer talks to another server through WCF, and the service layer can be refreshed in between calls by the web layer. 这在SOA中很常见,其中外部Web层通过WCF与另一个服务器通信,并且服务层可以在Web层的调用之间刷新。

The .NET Garbage collector cleans up circular references without problem. .NET Garbage收集器可以毫无问题地清除循环引用。

It does not count references to objects like the old VB6 GC. 它不计算对旧VB6 GC等对象的引用。
It traces active objects by traversing all objects in memory starting with special "object roots". 它通过从特殊的“对象根”开始遍历内存中的所有对象来跟踪活动对象。

More simply put: 更简单地说:

When the garbage collector runs, it starts from things like memory registers and static fields and such. 当垃圾收集器运行时,它从内存寄存器和静态字段等开始。 These are known as "Roots". 这些被称为“根”。

From there, the garbage collector follows references from the root to other instances of objects. 从那里,垃圾收集器跟随从根到其他对象实例的引用。 This creates a graph of all objects reachable from the roots. 这将创建从根可到达的所有对象的图形。

If your objects are not reachable from the roots, then they are considered unreferenced and can be cleaned up by the garbage collector. 如果您的对象无法从根目录访问,那么它们将被视为未引用,并且可以由垃圾收集器清理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM