开发者

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

I'm concer开发者_Go百科ned 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 ...

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.

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?

This is a serious concern because it is an ASP.NET application. 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.

Possible negative results:

<< Webserver crashes due to RAM overflow.

<< Webserver crashes due to infinite Garbage Collection loop.

How does .NET handle Garbage Collection in this type of scenario?


The .NET GC works by tracing rooted references, such as static fields and in-scope local variables. It handles reference cycles properly. e.g. If A <--> B, but neither is referenced from a rooted reference, it is collected.

Let's consider how the GC determines when it can reclaim memory. When the CLR attempts to allocate memory and has insufficient memory in reserve, it performs a garbage collection. The GC enumerates all rooted references, including static fields and in-scope local variables on any thread's call stack. 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. 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


If A -> B, B -> A and there is no other reference to A and B, the GC is smart enough to free these objects.

In ASP.NET, there is the added insurance of an app pool. 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. 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. 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.


The .NET Garbage collector cleans up circular references without problem.

It does not count references to objects like the old 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜