前些時候游戲莫名其妙出現大量內存泄露,我感到很詫異,當然一般情況下游戲的內存管理是極其嚴苛的,出現如此大量的內存泄露到底是怎么回事?
句柄濫用導致的內存泄露會多誇張呢,尤其SOCKET,在某些客戶端系統下,短短5個小時可以吃掉5GB以上內存,有甚者達到6GB,並且進程內存查看非常完好,並無激增,那內存去哪了?看看我們的排錯過程。
排錯過程:
1、首先我們第一反應還是內存泄露,但是觀察進程發現占用非常合理,並沒有絲毫的激增情況,甚至運行周期后還會出現下降的情況,此類情況用資源管理器和性能管理器可以進行排錯,從而進一步確定不是游戲本身所申請的內存泄露。
這里包含 MALLOC,NEW等方式。
為了安全期間,采用VLD進行內存泄露排錯,預計結果和我猜測的一樣,並無激增或泄露。
此處步驟必須,用於排除激增或可能存在激增的內存問題,在LINUX下有其他庫請自己查找,至於此地由於是客戶端泄露,采用的VLD庫用於內存泄露排錯。
2、其次我們發現是系統在申請並歸屬於該進程的一塊內存區域,就像共享內存一樣,此時已經初步認定為句柄未釋放導致的內存泄露,那么如何定位?
首先要讓內存產生泄露,然后請出PCHunter,啟動后找到游戲目標進程,右鍵查看進程句柄。
此時可以看到句柄數已經非常異常,數量高達1182個之多,有些進程甚至過萬,這是明顯的異常,除非一般的服務端進程,通常情況下句柄數不會達到如此之數。
然后要定位是什么句柄導致的系統內存激增,通過數量分析發現有一項神奇過多:
File \Device\Afd 0x00000B38 0xFFFFE0005183E070 30 32758
此處的 \Device\Afd 為關鍵,該類型代表為SOCKET句柄,此處已經徹底定位到原因,是SOCKET創建句柄但未釋放導致的異常。
3、以上方法已經定位到基本錯誤,確定是SOCKET,但是怎么知道是哪里呢,這就要監控所有SOCKET創建的地方,我這里是因為使用了第一個第三方的PING庫,而這個庫代碼只創建SOCKET不關閉SOCKET。
所以產生以上問題,簡單解決只要關閉不使用SOCKET即可解決,重點在於定位是異常難的,所以特寫此文。