-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Hi,
I found an odd behavior of System.Runtime.CompilerServices.ConditionalWeakTable<TKey, TValue>
in both .NET Core and .NET Framework which looks like a bug to me: If you create multiple instances of the ConditionalWeakTable
and store a key-value pairs in them, where the key stays alive and the value contains a reference to the ConditionalWeakTable
, the values are not garbage-collected after they (and the ConditionalWeakTable
s) are no longer referenced.
For example, create a .NET Core Console application with the following code:
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
object key = new object();
while (true) {
var table = new ConditionalWeakTable<object, Tuple<object, byte[]>>();
table.Add(key, new Tuple<object, byte[]>(table, new byte[1000000]));
GC.Collect();
}
}
}
}
Expected behavior: The memory consumption of the program should stay in the same area, because when a new ConditionalWeakTable
instance is created, there are no more references to the previous ConditionalWeakTable
and its Tuple
value, so they should be able to be reclaimed by the Garbage Collector.
Actual behavior: The memory consumption rises rapidly (4 GB after some seconds) until an OutOfMemoryException
is thrown, as the byte arrays are not reclaimed by the garbage collector.
However, if you remove the reference to the table by replacing table.Add(...)
with table.Add(key, new Tuple<object, byte[]>(null, new byte[1000000]))
, the problem disappears.
If the algorithm cannot be implemented such that it can detect that there are no more references to the table and its values, I think the ConditionalWeakTable
should implement a Dispose()
method that allows to clear all key-value-pairs.
The behavior is the same for .NET Core (.NETCoreAPP 1.1) and .NET Framework 4.6.2.
Thanks!
Metadata
Metadata
Assignees
Labels
Type
Projects
Status