GC detects leaks for items that are added to the List field of the base class, when the class scope allocated.
I have a base class that defines append list and derived class that have a method that allocates new items and adds it to the list. However, after allocating the class on stack and calling that method, after a few seconds GC detects memory leaks, even though the list field has a destructor that deletes all items.
Code example
class Program
{
static int Main(String[] args)
{
var test = scope Test2();
test.AddItems();
while(true)
{
Thread.Sleep(500);
}
}
}
class Test1
{
public append List<TestItem> Items ~ ClearAndDeleteItems!(_);
}
class Test2 : Test1
{
public void AddItems()
{
Items.Add(new TestItem());
Items.Add(new TestItem());
}
}
class TestItem {}
Output:
Think I've found another example of this problem:
public struct A : IDisposable
{
public List<float> list = new .();
public void Dispose()
{
delete this.list;
}
}
public struct B : A
{
}
public class C
{
public B b = .();
public ~this()
{
this.b.Dispose();
}
}
static
{
public static void Main()
{
C c = new .();
Console.Write("Sleeping... ");
System.Threading.Thread.Sleep(3000);
// Crashes with a memory leak (on A's list) before reaching this call.
Console.WriteLine("done!");
delete c;
}
}
Some additional oddities:
- Sleeping for shorter periods of time avoids the crash. From experimentation, 2000 ms seems to be about the threshold where the memory leak stops.
- Removing the first
Console.Writeavoids the crash, even when sleeping for much longer periods of time (say, 10 seconds or longer). - Using an
Ainstance withinC(rather than aBinstance) avoids the crash:
public class C
{
// Doesn't leak!
public A a = .();
public ~this()
{
this.a.Dispose();
}
}
-
Composing
AwithinBrather than inheriting avoids the crash:
public struct B : IDisposable
{
// Doesn't leak!
public A a = .();
public void Dispose()
{
this.a.Dispose();
}
}
4589e7ea0ea4121baea76e2a7bc488398a3279bd should fix the @Grimelios issue, which was a simpler and higher-priority fix, but the append object issue remains
Fixed at d9ce23ac8e5e44c2952c33c5c835ecba9a1df094