.NET Framework - Possible memory-leaky classes?
Just the other day I was investigating a memory leak that was ballooning the app from ~50MB to ~130MB in under two minutes. Turns out that the problem was with the ConcurrentQueue class. Internally, the class stores a linked开发者_Python百科 list of arrays. When an item is dequeued from the ConcurrentQueue, the index in the array is bumped, but the item remains in the array (i.e. it's not set to null). The entire array node is dropped after enough enqueues/dequeues, so it's not technically a leak, but if putting large objects in the ConcurrentQueue, this can get out of hand fast. The documentation makes no note of this danger.
I was wondering what other potential memory pitfalls are in the Base Class Library? I know about the Substring one (that is, if you call substring and just hold onto the result, the whole string will still be in memory). Any others you've encountered?
You are correct. The bug is located in the method System.Collections.Concurrent.ConcurrentQueue<T>+Segment.TryRemove(out T, ref ConcurrentQueue<T>.Segment)
.
If you look at this method in Reflector, you'll see the following line:
result = this.m_array[low];
There should be the following line after it:
this.m_array[low] = default(T);
For reference, you can see how this is correctly implemented in the method System.Collections.Generic.Queue<T>.Dequeue()
.
Though not a direct memory leak or specific to .net/BCL, there is the string concatenation (using the += operator) issue. That's pretty CPU intensive in loops due to heavy garbage collecting.
The ConcurrentQueue will hold only a maximum of 31 dequeued objects. This shouldn't present a huge problem unless you're dealing with really large object graphs.
Anyway, it doesn't make sense using a ConcurrentQueue if you don't have enought space to allocate 32 objects...
精彩评论