美文网首页
一个致命的bug

一个致命的bug

作者: fooboo | 来源:发表于2018-11-28 00:17 被阅读29次

    至于多严重?影响所有玩家,不管在线还是离线,数据都被写坏。

    今天出现一个非常非常严重的问题,导致所有玩家数据写坏,且无法创建新角色,老角色也无法进行游戏,且一直刷报错。底层框架lua虚拟机中有个class,class有个字段synckey,类型为table,里面存放了要同步的key,即在服务端有一个类表示玩家类,然后每个字段有不同的同步级别,所以为了优化,把要同步的key用一个table缓存起来,所有同一个class的实例共用一个synckey。

    问题是每个玩家的Sex变成了***,所以一进游戏就报错,也影响了其他使用Sex字段的模块。为什么突然会出现这样的问题的,因为之前测试过很多次了,并没有出现。然后要写坏也不会因为这个Sex,所以比较棘手。线上问题最棘手了。

    后来大伙猜测是不是因为Sex是敏感字,被替换成了*** (受这个启发的是因为其他敏感词被替换成*** ,而且代码中并没有修改synckey)。因为这个模块是接的腾讯的,然后测试时,有些词库并不全,所以并没有把每个词都测试一遍,即我输入聊天内容为Sex,然后被替换成***。

    因为真的没有去修改底层的代码,而且这是个key,并不是value,然后影响了所有功能,包括数据,哪怕玩家上次登出时数据正常,下次登录时,出现GetSex(),变成了Get*** ()这样的调用而报错,且玩家的数据字段由Sex:0变成***:0这样的问题。因为调用一个方法是通过Get..Sex这样形成字符串并定位到类的函数的。

    为了复现这个问题,在本地词库中添加Sex,即要被过滤成***的,然后打开检查,输入聊天内容Sex,然后角色登出游戏,再登录就出现一样的问题,即定位到问题了。但好奇是为什么会被替换的。后来定位到c代码,即把聊天内容通过第三方接口去检查。

    我看提供的接口声明,大致这样 int32_t checkChat(const type* rhs)类似的接口,因为我看它是const形参,表示不会改实参的内容,当时这块我优化过。
    原来对从lua层传送的chat内容进行了一次拷贝,大致这样 char buff[MAX_CHAT_BUFF_SIZE],const char *pChat = luaL_checkstring(L, index), memcpy(…),structChatData.Chat = buff这样,因为看到luaL_checkstring源码返回为const,表示不能改内容。然后我看了下第三方的接口,为什么不直接使用pChat呢?因为这个接口是同步接口,后来被我优化成如下形式structChatData.Chat=pChat,后来一直没出问题。

    恰恰因为这样,然后调用checkChat时,那边检查到chat是敏感词,然后修改了structChatData.Chat 指向的内容,被替换成了***,由于lua本身的实现,对于小字符串,只有全局一份。所以只要被修改,都会影响前面的。所以问题在这里,由于接口会修改实参,且实参的内容是lua层的,所以就破坏了const规则,破坏了数据。

    bug虽然被同事修复了,但是如何修正所有玩家字段Sex变成*** 的情况呢?只在在某个地方去判断是不是*** ,是的话重新设置Sex,这里比较复杂不说了。
    其实有个问题一直困扰我,就是使用别人的接口,如果看不到实现,是否要完全相信如函数声明那样,如果是checkChat并且const type*,表示只做检查,不修改参数内容,是否要遵守约定?如果修改就checkAndModifyChat(type *)这样?

    还有个,对于lua,比如我有个类struct stu,其中有个名字,在c/c++中,应该是stu.Name=“xiaowang”这样赋值,是偏移量,大小可能是一个string实际的大小或者是个char数组,且只存value,而在lua中,则要存key和value和类实例名,stu.Name=“xiaowang”,这样stu是个table,Name是个字符串,且进行hash存入stu表中,xiaowang也是个字符串作为key的value。如果不小心把key修改了就永远定位不到原来value。

    之前也写过相关的使用第三方接口的记录,对于这块,还是看代码规则怎么约定吧。

    相关文章

      网友评论

          本文标题:一个致命的bug

          本文链接:https://www.haomeiwen.com/subject/pieoqqtx.html