這一段時間太累了,周六還是要開始加班了,工作日每晚回家洗洗都十一點了,偶爾出版本都十二點后,今天就早點回來了,把這周遇到的問題總結一下。
這周主要工作是幫派功能的開發,次要工作是解決測試提的bug。遇到兩個bug,一個是服務器背包數據正確,下發給客戶端的指令也是正確的,但是客戶端無法識別哪個先后執行,造成有點失誤。
背包功能改了大概三次了,第一次我做的是增量更新,客戶端請求。即每件物品有個修改時間和創建時間,要是物品的一些屬性字段更新了就修改更新時間字段,客戶端請求時間和更新時間字段對比,把有變動的下發,這樣節省了流量和服務器處理時間,時間復雜度常數;第二次是服務器主動通知【走notify消息】,leader也給了一種思路,即每個物品各自有個標志,操作了該格子后就設置1,然后統一刷新,最后重置0,這樣有個問題就是如果有一個格子變動,都要遍歷所有格子,時間復雜度線性時間;第三種我只把有變化的主動通知給客戶端,時間復雜度是常數【一個操作單元只會涉及到少量幾個格子數據的變化】;然后消息中有增加的物品列表和刪除物品簡要信息的列表指令告知客戶端,問題出現在一個操作單元【一個CSReq---CSRes】中,比如背包1格子0,記為{bag = 1, slotid = 1}中有個道具,我使用后的效果是獲得一件裝備,此時我下發給客戶端的消息指令是:增加一件裝備,刪除一件道具,如果這兩個操作指令涉及到的不是同一個背包切同一個格子就不會有問題,反之,客戶端是不知道先增加后刪除,函數先刪除后增加。【先用裝備覆蓋原來道具的位置,再執行刪除那個位置,那么什么都沒有了;或者先刪除那件道具再添加裝備,后者才是正確的結果】
經過與客戶端討論,服務器要么修改通知更新背包的協議,要么下發的指令保證不會出現同一個背包和格子,后來我在代碼中把涉及背包操作的代碼都增加了個操作時序,這樣就有先后了,然后下發給客戶端時稍微處理下,就解決了背包刷新問題【增加裝備比刪除后執行,結果是只下發增加裝備的指令】。當然還有其他思路。
第二個bug真的很難重現,B玩家對象釋放了A玩家對象的某一部分數據。玩家對象分配在XX出,某一部分數據分配在YY處,XX中有引用YY的索引【這個保證了熱啟動時可以恢復】,然后玩家P正常登陸,分配XX中的A,分配YY中的B,然后下線釋放A,和B。釋放只是解除引用關系和設置標志表示該空間不再被使用【好比函數調用分配棧空間,ret時,esp回退的時候,那些先前函數棧的數據還存在但不能引用】但是那個索引值如1是臟值,然后Q玩家對象創建了,分配了XX中的空間A,但處于某個狀態比如等待玩家輸入名字等步驟完成后再初始化數據,此時并沒有分配YY中的空間,但A中有索引值1,然后玩家P登陸,分配XX中的C,分配YY中的B,索引也是1【分配總是從下一個未被使用的空間開始,里面的實現是可用空間組成了一個串鏈,每個串有一個索引字段指向下一個可用空間】,P玩家數據正常,然后Q進行到一半就斷線了就刪除該A,然后釋放分配在YY中的空間,因為索引為1,正好釋放了,而不管這個1是P對象還是Q對象的,導致P正常下線時獲取不到某部分數據,寫數據庫時丟失了一部分數據。
類似于一個指針P指向A,然后釋放A空間,指針P沒有被賦為NULL,然后那個地址被另外的變量使用了,然后這里P再次操作A,導致修改了別人家的數據。
解決辦法是只有在初始化玩家數據成功時,才釋放YY中的數據,添加了一個標志,在初始化時設為true,回收時設為false,這樣就沒有問題了。
有時編碼時沒能把每一種異常考慮進去,導致出現了邊界異常,這樣較難發現。需要對著日志慢慢分析。