2010-04-11 58 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代碼中內存泄漏的首要原因,因爲事件仍然在調用列表(因此也是對象)中被引用。