CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Apr 1999
    Location
    Galway, Ireland
    Posts
    96

    Angry Memory Leak in C#???

    I am having a problem with memory in a windows service I created in c# vs2003. The service activates once a day and performs a large operation. Using the resource monitor I can see the service grow to several hundred megabytes which it does not release.

    The service contains a timer which fires an event once a minute. That event calls a function called Harvest() every 24 hours. Several classes are called in Harvest which populate many ArrayLists, hence the size of the service. However, all these classes are declared locally within the scope of Harvest(). So when Harvest completes, they go out of scope, and the garbage collector should kick in within a reasonable amount of time.

    The service ran at 2:00am and this morning at 9 the memory footprint was still several hundred megs. I've tried forcing the local variables to null, called GC.Collect(), even GC.ReRegisterForFinalize(object). Nothing worked.

    None of the code called is unmanaged. Havest() locally instantiates wrapper classes around the SharePoint Portal 2003 object model, which is written in .NET. Obviously something is amiss with this but I can't figure out why when it goes out of scope it won't clean itself up. There are several Close() methods for some SharePoint objects, but calling them makes no difference (as this happens automatically when they go out of scope). I can even issue an iisreset which kills SharePoint but the memory footprint does not change.

    Has anyone encountered a similar problem or used tools compatible with C# which could help?

    Right now I am wishing I was writing in C++!

  2. #2
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: Memory Leak in C#???

    C#'s variables dont get destroyed when it leaves scope (neither does a new obj in C++ btw).

    a good rule of thumb is, if it has a Dispose method, invoke it *as soon* as you're done with it.

    the more you mess with the gc the less likely its going to work correctly for you. if you dispose items when you're done, you'll keep things in check.

  3. #3
    Join Date
    Apr 1999
    Location
    Galway, Ireland
    Posts
    96

    Re: Memory Leak in C#???

    A new'ed obj in C++ requires a delete. A local object in C++ calls its destructor when leaving scope. Unless I misunderstand the garbage collector completely, if its declared locally in a function and the function exits the reference goes to 0 which marks it to be cleaned up.

    As I mentioned already, I have called Close() (which in turn calls Dispose) for all the SharePoint objects which have that method.

    Lastly, I'm not messing with the GC because that's the way I designed the program. I'm merely attempting a few things because of the problems I encountered leaving the GC to its own devices.

    I'd appreciate some helpful advice.

  4. #4
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: Memory Leak in C#???

    sorry I wasnt helpful. I'll remember to keep to myself next time.

  5. #5
    Join Date
    Apr 1999
    Location
    Galway, Ireland
    Posts
    96

    Re: Memory Leak in C#???

    No worries, my fault for only posting here when I'm frustrated. Its hard to tell who is a newbie sometimes.

    Here is the solution, for better or worse this resets the memory footprint. I run the following at the end of the Harvest() function when the locally instantiated SharePoint wrappers go out of scope.

    Code:
    //For the sake of the memory footprint in Task Manager
    GC.Collect();
    System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet;
    Last edited by Chris Green; August 9th, 2005 at 10:10 AM.

  6. #6
    Join Date
    Oct 2004
    Location
    Rocket City
    Posts
    220

    Re: Memory Leak in C#???

    Is the parent app still running even though Harvest is not? Perhaps Windows, in the interest of VM efficiency, retains handles to the memory in case you might want to access the same thing again, as long as NEWER demands are not made for the same memory. Just an odd thought.

  7. #7
    Join Date
    Mar 2004
    Location
    (Upper-) Austria
    Posts
    2,899

    Re: Memory Leak in C#???

    Quote Originally Posted by Chris Green
    A new'ed obj in C++ requires a delete.
    Yes but in most cases you won't wright it on your own

    Code:
    void foo ( void )
    {
       auto_ptr<MyClass> myObj ( new MyClass );
    
       // Do something with myObj, and let auto_ptr delete the object
    }
    I am not offering technical guidiance via email or IM
    Come on share your photo with us! CG members photo album!
    Use the Code Tags!

  8. #8
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Memory Leak in C#???

    Unless I misunderstand the garbage collector completely, if its declared locally in a function and the function exits the reference goes to 0 which marks it to be cleaned up.
    Firstly, the GC doesn't work by a reference count approach. It uses a broader approach to mark memory for release.

    Secondly memory is only released when the GC has to. Which is why it appears to build up to an absolute maximum and then drops down.

    It doesn't release memory immediately : it waits until it's got lots of memory to be released and then does it in one block.

    Thirdly, the GC likes lots of little classes rather than a few big ones. It assumes larger classes will survive longer than smaller ones (or something like that). I've written about this before and it's one of my likes about C# : good object orientation is rewarded by faster running and smaller footprint exes than bad object orientation.

    GC.Collect() has been put into the framework for the very reason that you've found : i.e. when you need to force the GC to do its garbage collection at a specific point. Personally I've never had to use it : and I've written some very large apps in my time with C# with a lot of memory allocations.

    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  9. #9
    Join Date
    Feb 2005
    Posts
    106

    Re: Memory Leak in C#???

    What does the footprint look like if give the process a bikini wax with SetProcessWorkingSetSize()? This will give you a better look at your mem consumption.

    Regards.

  10. #10
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Memory Leak in C#???

    Okay, I've just looked up how the GC works, and here it is in a nutshell (for completeness).

    Reference counts are NOT used. The main reason for this is because you can end up with circular references (e.g. in linked lists etc).

    A concept of "roots" is employed. This states that you can determine all used references in the system by considering

    (1) All global/static variables.
    (2) All local references to memory at the current point of execution.
    (3) All references to memory held in the CPU registers.
    (4) References to objects in the Ready To Finalize list.

    When performing garbage collection, the GC first assumes that all memory on the heap (i.e. dynamically allocated) is garbage.

    Then it runs through the above 4 "roots" finding objects which are still active.

    After this, it knows what memory is garbage and releases it.

    In addition, there is the concept of "generations" in the GC. There are 3 generations :

    Generation 0 : Objects which haven't gone through a GC cycle yet.
    Generation 1 : Objects which have gone through a single GC cycle and survived.
    Generation 2 : Objects which have gone through more than one GC cycle and survived.

    Memory is taken from the lowest generation first : therefore once all the memory in Generation 0 has been used, the memory in Generation 1 is garbage collected and used. Likewise for generation 2.

    Therefore long-lasting memory is less likely to be released than short-lasting memory. Which is probably what is happening in your case.

    To explicitly mark an object for release, set the variable reference to "null" i.e.

    Code:
    byte [] abChars = new byte[1000];
    abChars = null; // explicitly mark the memory for release
    Darwen.
    Last edited by darwen; August 11th, 2005 at 05:19 AM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  11. #11
    Join Date
    May 2003
    Location
    Corvallis, OR
    Posts
    315

    Re: Memory Leak in C#???

    Very nice insight in this post. I am making the switch over from C++, so I am having to relearn how to handle memory in C#.

    In C++, I make a habit of checking for valid pointers before using them...
    Code:
    CMyClass* pClassPointer = NULL;
    pClassPointer = new CMyClass();
    if(pClassPointer == NULL)
    {
       ASSERT(FALSE);
       return FALSE;
    }
    
    pClassPointer->m_intMember = 7;
    delete pClassPointer;
    pClassPointer = NULL;
    return TRUE;
    The above code is safe way (I've found) to use pointers.

    My question is, do the same rules apply in C# for reference types? That is... if I use a reference type, should I first check to see if its null, and then when I'm done, should I set it to null (the equivalent of delete i C++)? In doing this, do I expel the risk of a memory leak?

  12. #12
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: Memory Leak in C#???

    .net is pretty good w/ memory management. not everything is managed though. so the best practice is to call the Dispose method on objects implementing IDisposable (if there isnt a public Dispose method on the IDisposable object, setting it = null will do the same thing as calling the dispose method) when youre done with it.

  13. #13
    Join Date
    May 2003
    Location
    Corvallis, OR
    Posts
    315

    Re: Memory Leak in C#???

    Why wouldn't you just derive every user-defined class from IDisposable and Dispose() of all reference type variables as soon as you are finished? Wouldn't this be the safest and most memory efficient method?

  14. #14
    Join Date
    Mar 2004
    Location
    33°11'18.10"N 96°45'20.28"W
    Posts
    1,808

    Re: Memory Leak in C#???

    most classes are purely managed by the built in garbage collector. objects that are unmanaged or interop w/ unmanaged code should use the disposable interface for that, so that their unmanaged resources can be "deleted." managed objects are allocated & managed in the gc heap, but some of what they use might be allocated in unmanaged memory, so while the object that contains references to the unmanaged objects might be deleted, the actual items in unmanaged memory will be left orphaned. with the managed items, finializing them is a matter of timing more than anything else. Dispose is the 'do it now' directive. if that object has unmanaged items, then they are cleaned up then. otherwise the object will be cleaned out at some later time.
    Last edited by MadHatter; March 9th, 2006 at 12:46 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured