tags:

views:

35

answers:

2

I have a rather large and complex game in C#, and in it are various monsters. The monsters are created in the game by a MonsterCreator, and each monster has various plugins that are loaded from external DLLs.

When my monsters die, they call a method in the MonsterCreator, and the MonsterCreator removes them from the game map, removes them from its own internal list of monsters, and then finally calls the Dispose() method on the monster itself.

The dispose method calls the dispose method of each plugin, then clears up any of its own code.

This seems to work fine, with lots of monsters, but somewhere there is a bug that crops up after a while, where a monster dies, but it has already been removed - it seems the callback telling the MonsterCreator is being called over and over, when the monster should have been removed on the first call.

The likely candidate is that some of the plugins for the monster register themselves with an Event that pulses them every X number of seconds so they can perform logic. Stepping through I can see that they are unregistering with the Event when they die, but something is getting through still and I don't know what it is.

Do you have any advice for debugging the problem? I can't post code really because it's split across a ton of libraries and plugin dlls, so it's more a case of figuring out the best way to debug it.

I threw an exception in code when the monster died callback method is thrown and the monster cannot be found on the map to be removed, so I have the misbehaviing Monster, is there a way I can see what is still linked to it?

+2  A: 

You will need to use a profiler that will show you the connected graph. Something like the redgate ANTZ memory profiler.

Having said that, if you are using events, you need to be sure to un-register them. Failing to do so is the number one cause for memory leaks in .NET code, as the event is still referenced in the invocation list (and hence the object).

Oded
+1  A: 

Beware that Dispose doesn't remove the references that the other objects might have to your Monster object! So the other objects referencing your Monster can report that the Moster dies after it had actually died.

Another popular source of mistakes is not unsubscribing from events: each subscribing to Monster's events makes (implicitly) a reference to the Monster instance.

Vlad
Is there any way to remove all references? What happens if another monster sets its CurrentTarget variable to be your Monster, then another Monster kills it? The CurrentTarget will remain and so will your monster? How can I keep track of so many...!
SLC
Actually, in this case CurrentTarget will keep the reference to your Monster until explicitly released (in Dispose() or after being garbage collected). For a given object, there is no way to know all the references to it :-(
Vlad
But there is another possibility: you can keep `WeakReference`s to your monster. This way every time you try to access your Monster by weak reference, you'll need to obtain a strong reference. Obtaining a strong reference will fail if the object is already dead, you'll get just a `null`. You should however check that your object is not being `Dispose()`d at the moment.
Vlad
Ooh weakreferences sound good, I will google them up. As for my problem I think (pray) its not as bad as I thought. I left it in debug mode for 15 minutes and it hit the line it shouldnt have, it looks like my monster may be being killed twice simultaneously (presumably by 2 monsters attacking together) and thus it calls the death method twice. More investigation needed though!
SLC