2010-04-11 57 views
0

我在C#中有一个相当庞大复杂的游戏,并且里面有各种各样的怪物。怪物是由MonsterCreator在游戏中创建的,每个怪物都有各种从外部DLL加载的插件。如何找出什么阻止我的物体正确处置?

当我的怪物死亡时,他们调用MonsterCreator中的方法,MonsterCreator将它们从游戏地图中移除,将它们从其自己的内部怪物列表中移除,然后最终调用怪物本身的Dispose()方法。

dispose方法调用每个插件的dispose方法,然后清除它自己的任何代码。

这似乎工作正常,有很多怪物,但有一个地方有一个错误,在一段时间后出现一个怪物死亡的地方,但它已经被删除 - 看起来这个回调告诉MonsterCreator被称为一次又一次,当怪物应该在第一次通话时被删除。

可能的候选者是怪物的一些插件向它们自己注册一个事件,该事件会每X秒钟触发一次,以便它们可以执行逻辑。走过去,我可以看到他们在事件发生时注销了他们,但有些事情仍在继续,我不知道它是什么。

您对调试问题有任何建议吗?我无法真正发布代码,因为它分布在大量库和插件DLL中,所以更多的是找出调试它的最佳方式。

我在抛出怪物死亡回调方法时抛出了一个异常,并且在地图上找不到可以移除的怪物,所以我有不正当的怪物,有没有办法我可以看到仍然存在的东西它?

回答

1

请注意,Dispose不会删除其他对象可能对您的Monster对象造成的引用!因此,参考您的Monster的其他对象可能会报告Moster在实际死亡后死亡。

另一个流行的错误来源并不是取消订阅事件:每个订阅Monster的事件都会(暗含地)引用Monster实例。

+0

有什么办法可以删除所有引用吗?如果另一个怪物将其CurrentTarget变量设置为你的怪物会发生什么,那么另一个怪物会杀死它? CurrentTarget将会保留,你的怪物也会保留吗?我如何跟踪这么多......! – NibblyPig 2010-04-11 11:00:05

+0

实际上,在这种情况下,CurrentTarget会保留对你的怪物的引用,直到明确释放(在Dispose()中或垃圾回收后)。对于一个给定的对象,没有办法知道所有对它的引用:-( – Vlad 2010-04-11 11:07:18

+0

但是还有另一种可能性:你可以保留'WeakReference'给你的怪物。这样每次你通过弱引用访问你的怪物时,你需要获得一个强大的引用,如果对象已经死了,那么获得一个强引用就会失败,你只会得到一个'null',但是你应该检查你的对象是不是'Dispose()'d – Vlad 2010-04-11 11:09:52

2

您将需要使用一个分析器来显示连接的图表。像红门槛ANTZ memory profiler

话虽如此,如果您使用的是事件,您需要确保取消注册它们。如果不这样做是.NET代码中内存泄漏的首要原因,因为事件仍然在调用列表(因此也是对象)中被引用。