Seeker.cs leaked managed shells

Hey there,

So I stumbled across this when trying to patch up memory leaks in our project. You need to make sure anytime you are caching a delegate in a class to avoid repeated delegate allocations (we do this a ton in our project), that you null them out or it will lead to a “Leaked Managed Shell” in the Memory Profiler. I discovered this from the Memory Profiler, and confirmed the fix afterwards.

image

Hi

Once the Seeker is destroyed, and assuming it is not referenced from some other location, the GC will be able to collect it and all the delegates stored inside of it. Clearing the delegates manually should not be necessary unless you are somehow holding on to a reference to the Seeker component.

The delegates are holding a self reference. When you cache them in the constructor here:

public Seeker () {
	onPathDelegate = OnPathComplete;
	onPartialPathDelegate = OnPartialPathComplete;
}

The Seeker managed shell can’t be GC’d because it’s referenced by those delegates, and those delegates can’t be GC’d because they are referenced by the Seeker. I promise you, I’ve spent the last few days doing this to our whole project as we do lots of delegate caching. The Memory Profiler tells the whole story and can confirm that this fixes it.

Hi

A GC is able to handle circular references. It’s in fact one of the big selling points of GCs.
Are you sure there are no other references to the Seeker or other important references?

When I get some time, I’ll try to reproduce with a much simpler case (destroying a GameObject that only has a Seeker component) and report back.

1 Like