HEAP: Free Heap block xxxxxxxx modified at xxxxxxxx after it was freed


《諸子百家》發布后,發現游戲在有些情況下會崩潰。偶然崩潰。

       由於我是負責主框架,網絡協議和登錄,數據等,所以這個修正bug的任務主要就落在我頭上了。

      

       一、bug

       1.最頭疼的bug

       HEAP: Free Heap block xxxxxxxx modified at xxxxxxxx after it was freed

 

       這個是最頭疼的。知道崩潰了,知道內存地址,但是不知道在哪個文件。跟蹤了好幾天,打了很多日志,沒頭緒。后來網絡上一找,也有很多人碰到這個問題。主要的解決方案是下載使PageHeap.EXE或GFlags.EXE檢查內存越界錯誤,還有就是用WinDbg.

       於是屁顛屁顛的把這些都下下來,搞了一陣子,發現不實用。主要是我們游戲里面,代碼文件還是蠻多的,300多個文件,代碼行估計有20萬行~ 這個里找錯誤還真不好找,工具也沒辦法定位到具體的文件。

       想了很久,后來覺得自己把問題想的太復雜了。

       上面的錯誤很典型的就是內存已經被釋放了,后面還繼續使用。簡單點說就是野指針!而造成野指針的原因很簡單,就是內存被釋放了。

       於是,問題變簡單了:找出所有釋放內存的地方。

       釋放內存的,主要就2個:free和delete.

       於是,我使用了2個宏,S_DEL(p) if(p){delete p; p=NULL;}

       S_FREE(p) if(p){free(p); p=NULL;}

       然后把所有用到這兩個的地方都用宏替換掉,然后再把這兩個宏里面真正釋放的給注釋掉。再跑,發現很OK,不會崩潰了。 於是,確認了是釋放引起的。

       然后在逐個把兩個宏里的釋放打開,發現打開S_FREE沒問題,於是范圍縮小到S_DEL里了。然后再把S_DEL里的釋放也打開,再按照模塊,把可以的地方用到的那個S_DEL注釋掉~~ 這個樣折騰了好久,最終找到了bug

      2. 郁悶的bug

      有時在團戰的時候,發現打到一定階段,程序就崩潰了。查看內存,看起來也沒什么特殊的。。。

      然后也是很長時間的排查。。。。。

 

      二.具體總結

     1. 經過很久的排查和使用上面的方法后,終於把這些崩潰點都解決了。主要有3個bug:

    1).AMF3協議里面。我們使用獨立的內存分配器進行內存的分配和釋放,保證不內存泄漏。內存不泄露這個目標是達到了,但是有時把正在用的內存給釋放掉了,造成了野指針。

      為什么會把正在使用的內存給釋放掉了呢?原來,在AMF3里,有一些數據是用引用的方式,而我們進行功能改寫時,使用了同樣的引用的方式,造成了多個節點使用同一個內存,因此導致其中某一個節點把這內存釋放后,其他使用這個的都變成野指針了。

      解決方案:不要使用引用,每個使用獨立的內存

      2)戰斗里面,我們有一些戰斗進度是用OnRender進行驅動的。比如A含有5個B,B含有10個C,我們的戰斗進度的驅動之一是是C的OnRender()。而OnRender是一直循環調用的,用這進行驅動的時候,如果符合了某一個條件,比如戰斗結束,那C通知B,B通知A,A就釋放內存,通知結束。這種模式的問題是,A釋放內存后,C返回到戰斗結束的觸發點繼續運行就崩潰了~

      解決方案:檢測到戰斗結束時,要所有的模塊退出OnRender,然后才釋放內存~

     

      3)用戶注銷重新登錄時,有時崩潰。

      原因是用戶注銷時,我們會把所有的內存釋放掉,把socket關閉。但是可能我們把內存釋放掉時,由於socket還在,所以繼續收到數據包進行AMF3的解析,而解析結果已經部分被清掉了,這個時候訪問,野指針,崩潰~~ 

       改成先把socket關閉,然后內存再釋放掉。發現,有時還是會崩潰~~ 后來發現,因為我們的socket是單獨線程處理的,也就是說我們釋放內存和關閉sockt的操作是在2個線程里處理,這樣總會出現一個先,一個后的,如果釋放內存比關閉socket先執行,則還是會出現野指針。

      解決方案:在socket線程里進行socket的釋放,等socket釋放完畢才進行內存的釋放~



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM