Original Post
When garbage collection causes memory leaks...
I''m sure that having read the subject of this thread you are thinking: "I thought garbage collection existed to prevent memory leaks!" Well it does, unfortunatly it''s causing me quite the head ach right now because some objects are not being released because of a trickly little referance to it which wont go away.
Anyone with any experiance in a garbage collected environment such as Java or C#, please read on.
Basicly, I am using C# to implement a game engine. This game engine will be using a fancy event system for notification of occurances in the game world.
This sounds cool and seems easy with the event handling functionality that .NET provides, but it has introduced a major memory leak where the memory is only realeased when the game shutsdown.
The games evironment class contains a delegate (function pointer that works on instances of classes) that is multicast (can point to multiple functions). When an event occurs, all the functioned referanced by the delegate are called, notifiying the classes which requested the notification.
Heres a quick, trimmed down snippit from my C# code:
Now lets say an NPC is instanced. It''s constructor requests a notification from the environment. Then our NPC dies. Normally he would be released from memory, however he is not because the garbage collector detects a referance to him still exists. Where? The Explosion VoidDelegate inside the Environment!!
The only solution I see is to remove all referances from multicast delegate by calling a function in NPC. Let''s see what this would look like.
Can anyone think of a better solution??
delegate void VoidDelegate();
class Environment
{
public Update()
{
// some explosion occurs
if(Explosion != null)
Explosion();
}
public VoidDelegate Explosion;
}
class NPC
{
public NPC(Environment env)
{
env.Explosion += new VoidDelegate(this.ReactToExplosion);
}
protected void ReactToExplosion()
{}
}
class NPC
{
public NPC(Environment env)
{
env.Explosion += new VoidDelegate(this.ReactToExplosion);
}
protected void ReactToExplosion()
{}
public RemoveNotifications(Environment env)
{
env.Explosion -= new VoidDelegate(this.ReactToExplosion);
}
}