Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does ListCollectionView leak memory?

I've been investigating how to avoid memory leaks caused by strong references to the INotifyCollectionChanged event from a view model. I was playing around with using a ListCollectionView to see if that would deal with it for me. I think that the following is leaking memory, am I doing something wrong?

var stuff = new ObservableCollection<string>();
while (true)
{
    var result = new ListCollectionView(stuff);
    // Just to keep make sure that the memory I'm seeing 
    // isn't waiting to be GC'd
    GC.Collect(); 
}
like image 937
Geoff Avatar asked Apr 21 '11 20:04

Geoff


People also ask

What can cause a memory leak?

In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which is no longer needed is not released. A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code.

Does exit cause memory leaks?

Improper terminationIf you terminate your program improperly though, their destructors might not be called, and then memory will be leaked. A common reason for this is using the exit function.

Is memory leak serious?

Very dangerous. Memory leaks in the kernel level lead to serious system stability issues. Kernel memory is very limited compared to user land memory and should be handled cautiously. Memory is allocated but never freed.

Can memory leak happen stack?

Stack memory leaks occur when a method keeps getting called but never exits. This can happen if there is an infinite loop or if the method is being called with different data each time but the data is never used. Eventually, the stack will fill up and the program will run out of memory.


4 Answers

The documentation for ListCollectionView is not great but if you noticed there is a method DetachFromSourceCollection. The remarks for this call mention unsubscribing and allowing garbage collection.

    var stuff = new ObservableCollection<string>();
    while (true)
    {
        ListCollectionView result = new ListCollectionView(stuff);

        //Use this method to unsubscribe to events on the underlying collection and allow the CollectionView to be garbage collected.
        result.DetachFromSourceCollection();
        //When finished set to null
        result = null;
        GC.Collect();
    }
like image 121
Brian from state farm Avatar answered Oct 21 '22 03:10

Brian from state farm


The CollectionView holds a reference to the source collection’s CollectionChanged event - hence GC can not collect the view until the source collection is disposed off and collected.

This is also clear from the documentation of CollectionView

    /// <summary>
    /// Detach from the source collection.  (I.e. stop listening to the collection's
    /// events, or anything else that makes the CollectionView ineligible for
    /// garbage collection.)
    /// </summary>
    public virtual void DetachFromSourceCollection()

This blog describes your issue and suggest two possible solutions:
http://www.eidias.com/blog/2014/2/24/wpf-collectionview-can-leak-memory ...

like image 32
Ahmad Avatar answered Oct 21 '22 04:10

Ahmad


I initially posted this as a comment, but I think it makes a better answer, so ...

a) if you're sure you've found a problem with the .NET framework, you're probably doing something wrong. It's not impossible, it's just not likely. b) that GC.Collect() isn't going to do what you're thinking it will.

I think you need to review how GC.Collect() works.


MSDN GC.Collect Method

Remarks

Use this method to try to reclaim all memory that is inaccessible.

All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to try to reclaim the maximum amount of available memory.


For starters, you don't show us where you're disposing of that memory that the ListCollectionView(stuff). You're just allocating new and allocating new, but you never dispose of the old. So yeah, it's going to leak like crazy. Until the GC runs and tries to collect.

If you do the same thing you demonstrate here with a list of strings it will most likely do the same thing. But for what you've shown, I expect it to leak.

like image 28
jcolebrand Avatar answered Oct 21 '22 02:10

jcolebrand


when you call GC.Collect, you variable result is still in scope so it won't be collected since there is one pointer to the data. anyway even if it wasn't the case. what garbage collection does is non deterministic as far as application code is concerned. like drachenstern said it will only try! and it will succeed eventually but you can't be sure when!

like image 20
Mehran Avatar answered Oct 21 '22 04:10

Mehran