這一段時(shí)間太累了殉摔,周六還是要開(kāi)始加班了,工作日每晚回家洗洗都十一點(diǎn)了记焊,偶爾出版本都十二點(diǎn)后逸月,今天就早點(diǎn)回來(lái)了,把這周遇到的問(wèn)題總結(jié)一下遍膜。
這周主要工作是幫派功能的開(kāi)發(fā)碗硬,次要工作是解決測(cè)試提的bug。遇到兩個(gè)bug瓢颅,一個(gè)是服務(wù)器背包數(shù)據(jù)正確恩尾,下發(fā)給客戶端的指令也是正確的,但是客戶端無(wú)法識(shí)別哪個(gè)先后執(zhí)行挽懦,造成有點(diǎn)失誤翰意。
背包功能改了大概三次了,第一次我做的是增量更新信柿,客戶端請(qǐng)求冀偶。即每件物品有個(gè)修改時(shí)間和創(chuàng)建時(shí)間,要是物品的一些屬性字段更新了就修改更新時(shí)間字段渔嚷,客戶端請(qǐng)求時(shí)間和更新時(shí)間字段對(duì)比进鸠,把有變動(dòng)的下發(fā),這樣節(jié)省了流量和服務(wù)器處理時(shí)間形病,時(shí)間復(fù)雜度常數(shù)客年;第二次是服務(wù)器主動(dòng)通知【走notify消息】,leader也給了一種思路窒朋,即每個(gè)物品各自有個(gè)標(biāo)志搀罢,操作了該格子后就設(shè)置1,然后統(tǒng)一刷新侥猩,最后重置0榔至,這樣有個(gè)問(wèn)題就是如果有一個(gè)格子變動(dòng),都要遍歷所有格子欺劳,時(shí)間復(fù)雜度線性時(shí)間唧取;第三種我只把有變化的主動(dòng)通知給客戶端,時(shí)間復(fù)雜度是常數(shù)【一個(gè)操作單元只會(huì)涉及到少量幾個(gè)格子數(shù)據(jù)的變化】划提;然后消息中有增加的物品列表和刪除物品簡(jiǎn)要信息的列表指令告知客戶端枫弟,問(wèn)題出現(xiàn)在一個(gè)操作單元【一個(gè)CSReq---CSRes】中,比如背包1格子0鹏往,記為{bag = 1, slotid = 1}中有個(gè)道具淡诗,我使用后的效果是獲得一件裝備,此時(shí)我下發(fā)給客戶端的消息指令是:增加一件裝備,刪除一件道具韩容,如果這兩個(gè)操作指令涉及到的不是同一個(gè)背包切同一個(gè)格子就不會(huì)有問(wèn)題款违,反之,客戶端是不知道先增加后刪除群凶,函數(shù)先刪除后增加插爹。【先用裝備覆蓋原來(lái)道具的位置请梢,再執(zhí)行刪除那個(gè)位置赠尾,那么什么都沒(méi)有了;或者先刪除那件道具再添加裝備毅弧,后者才是正確的結(jié)果】
經(jīng)過(guò)與客戶端討論气嫁,服務(wù)器要么修改通知更新背包的協(xié)議,要么下發(fā)的指令保證不會(huì)出現(xiàn)同一個(gè)背包和格子形真,后來(lái)我在代碼中把涉及背包操作的代碼都增加了個(gè)操作時(shí)序杉编,這樣就有先后了,然后下發(fā)給客戶端時(shí)稍微處理下咆霜,就解決了背包刷新問(wèn)題【增加裝備比刪除后執(zhí)行邓馒,結(jié)果是只下發(fā)增加裝備的指令】。當(dāng)然還有其他思路蛾坯。
第二個(gè)bug真的很難重現(xiàn)光酣,B玩家對(duì)象釋放了A玩家對(duì)象的某一部分?jǐn)?shù)據(jù)。玩家對(duì)象分配在XX出脉课,某一部分?jǐn)?shù)據(jù)分配在YY處救军,XX中有引用YY的索引【這個(gè)保證了熱啟動(dòng)時(shí)可以恢復(fù)】,然后玩家P正常登陸倘零,分配XX中的A唱遭,分配YY中的B,然后下線釋放A呈驶,和B拷泽。釋放只是解除引用關(guān)系和設(shè)置標(biāo)志表示該空間不再被使用【好比函數(shù)調(diào)用分配棧空間袖瞻,ret時(shí)司致,esp回退的時(shí)候,那些先前函數(shù)棧的數(shù)據(jù)還存在但不能引用】但是那個(gè)索引值如1是臟值聋迎,然后Q玩家對(duì)象創(chuàng)建了脂矫,分配了XX中的空間A,但處于某個(gè)狀態(tài)比如等待玩家輸入名字等步驟完成后再初始化數(shù)據(jù)霉晕,此時(shí)并沒(méi)有分配YY中的空間庭再,但A中有索引值1捞奕,然后玩家P登陸,分配XX中的C佩微,分配YY中的B缝彬,索引也是1【分配總是從下一個(gè)未被使用的空間開(kāi)始,里面的實(shí)現(xiàn)是可用空間組成了一個(gè)串鏈哺眯,每個(gè)串有一個(gè)索引字段指向下一個(gè)可用空間】,P玩家數(shù)據(jù)正常扒俯,然后Q進(jìn)行到一半就斷線了就刪除該A奶卓,然后釋放分配在YY中的空間,因?yàn)樗饕秊?撼玄,正好釋放了夺姑,而不管這個(gè)1是P對(duì)象還是Q對(duì)象的,導(dǎo)致P正常下線時(shí)獲取不到某部分?jǐn)?shù)據(jù)掌猛,寫(xiě)數(shù)據(jù)庫(kù)時(shí)丟失了一部分?jǐn)?shù)據(jù)盏浙。
類似于一個(gè)指針P指向A,然后釋放A空間荔茬,指針P沒(méi)有被賦為NULL废膘,然后那個(gè)地址被另外的變量使用了,然后這里P再次操作A慕蔚,導(dǎo)致修改了別人家的數(shù)據(jù)丐黄。
解決辦法是只有在初始化玩家數(shù)據(jù)成功時(shí),才釋放YY中的數(shù)據(jù)孔飒,添加了一個(gè)標(biāo)志灌闺,在初始化時(shí)設(shè)為true,回收時(shí)設(shè)為false坏瞄,這樣就沒(méi)有問(wèn)題了桂对。
有時(shí)編碼時(shí)沒(méi)能把每一種異常考慮進(jìn)去鸠匀,導(dǎo)致出現(xiàn)了邊界異常蕉斜,這樣較難發(fā)現(xiàn)。需要對(duì)著日志慢慢分析狮崩。