开发者

Memory Leak, Unsure if object is managed

I'm having trouble with a memory leak in C#. I'm seeing the memory usage in process manager increasing 10-20mb (and more) when no new objects should be getting created.

q1) I am under the impression that managed objects will automatically be deleted by the GC. But when I profile the memory usage using dotTrace, there seems to be +10k instances (in the show new / dead differences) of a basic object I wrote. I found the place that it would be leaking if this were c++,

public void TriggerEvent(string tEvent)
{
    oVariable tVar = GetVar(tEvent);
    if (tVar != null)
        sVariableParser.TriggerEvent(tVar);
    else
    {            
        tVar = new oVariable("@CXZ_TEMP_VAR", tEvent, 0, this);
        tVar._BlockDependancies = true;
        sVariableParser.TriggerEvent(tVar);
    }
}

Where oVariable is defined as

class oVariable : IComparable 

It seems that the GC is not deleting the new'd oVariables, I am wondering do I need to implement oVariable as IDisposable and ma开发者_C百科ke a specific system call to make sure the GC collects it? There are also a few other custom objects within oVariable, but I was under the impression that simple objects which don't use anything external (no COM objects etc) should automatically be managed, or am I mistaken and I've been created unmanaged data structures?

q2) Even with dotTrace Memory showing a lot of new oVariables where there should be zero (maybe the GC is lazy), I still have a feeling the memory leak could be coming from the windows forms, specifically DataGridViews. I was wondering if someone could tell me if I need to do any specific memory deallocation function calls after invoking a DGV update/redraw using

tGridView.Invoke(new UpdateGridViewCallBack(RedrawGlobalsViewGridView), tGridView);

I had assumed the new'd call back would clean up after itself.


First, do not call GC.Collect() it will force garbage collection, but has some nasty side effects. For example, it will push everything that is not ready for garbage collection back a generation and delay it's collection. MS has information about generations etc

Secondly, GC will only collect objects if there are no references to it.

So let's say your sVariableParser is a member variable that holds a reference to your tVar. When the GC runs, it's going to see that VariableParser is depending on tVar and not let it go.

Imagine that you have something like this:

public class House
{
   public Person Resident1 {get; set;}
}

public class Person
{
   public string Name {get; set;}
}

Then in your code you have

House.Resident1 = new Person {name = "John Calvin"};

When garbage collection runs, it can't clean up the Person object that is tied to Resident1 until House falls out of scope and is no longer used.

So all that is to say, that GC will clean up your references, but I'm guessing you've got some code holding on to your tVar, and you don't realize it.


First off, the GC isn't under anyone's direct control but the runtime's; it will run only when the runtime thinks it should. That means that objects scheduled for cleanup may persist for seconds or even minutes until the memory conditions indicate a cleanup should be performed.

However, 10,000 dead instances waiting to be cleaned up sounds like a memory leak. Some things to check:

Does oVariable contain or reference an unmanaged or IDisposable object? If so, oVariable should implement IDisposable and perform cleanup, releasing references to objects it does not "own", and/or disposing of objects it does control. There is a pattern you can use to avoid having to call Dispose() explicitly; look at http://www.codeproject.com/KB/cs/idisposable.aspx.

Does oVariable subscribe to any events of other objects? As long as the object with the event is in memory, any oVariable that has added its handler to the event will remain in memory, because the reference to the method will keep the object "alive" as far as GC is concerned. Again, you should create an IDisposable implementation and have the object remove itself from any events it listens to.

Lastly, I noticed in your comment to another post that you maintain hierarchical relationships, both upwards and downwards, to other oVariables. As long as an oVariable is in any of those lists, it's referenced. I would triple-check all code that adds and removes instances from these lists; you're forgetting to remove objects somewhere, so they hang around indefinitely. Again, disposing of an oVariable should involve (1) removing any reference to the variable as a Slave from any/all Master oVariables, (2) removing any reference to the variable as a Master from any/all of the Slaves, and finally (3) clearing the variable's Master and Slave lists. Only once the object is completely "orphaned" in memory will GC destroy it.


What does the internal implementation of oVariable look like? If you're using any assets that inherit IDisposable, you'll need to close them (or use a using block) to make sure they're properly disposed.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜