背景
今天有玩家反馈,某个技能的状态buff有概率会出现2个图标,并且状态层数不一样
开始排查问题
- 策划是不是又把资源图标配置错了?
- 最近没有配置新状态buff
- 前端代码排查后发现后端发来的状态数据为
status_list = {{status_id = 2, stacks = 5},{status_id = 2, stacks = 1}}
- 按理说,玩家身上的状态列表status_list,相同status_id只会保存一个数据
- 排查后端去重代码
- 后端 附加状态的 简易混淆 lua 代码
local apply_id_list = {} -- 带附加的状态列表 apply_id_list[2] = {} local status_id, new_status -- 遍历所有要附加的状态 for k, v in pairs(apply_id_list) do status_id = k v.status_id = status_id new_status = true -- 遍历玩家身上当前的状态 for i, info in ipairs(target_status) do -- 如果玩家有这个状态了,就不是新状态 if info.status_id == status_id then new_status = nil break else print("error--- ", info.status_id == status_id, info.status_id, status_id, for_i) assert(not (info.status_id == status_id)) end end if new_status then -- 如果这是一个新状态,就放入 target_status[#target_status + 1] = v end end
- 可以从简易代码看出,状态在附加的时候,是有判断玩家是否已经拥有当前状态的
- 后端 附加状态的 简易混淆 lua 代码
- 换一个思考方向,存放的target_status是个table,会不会是因为table的传递引用问题导致的?
- 如果 table 没有重新拷贝,那么可能其他地方对这个table数据修改,也会导致target_status中的内容也被修改
- 直接将 等待附加的状态复制成一个新table放入 target_status 中,发现问题依旧
- 没有思路,尝试更换附加另外一个状态
- !!! bug不会复现了 !!!
- 再次换回status_id = 2 的状态
- !!! bug又出现了 !!!
- 开始怀疑,难道这个status_id = 2 的状态有什么特别?
- 排查一遍状态脚本,并没有什么问题
- 在代码判断前,打印状态id数据
-- 遍历玩家身上当前的状态 for i, info in ipairs(target_status) do -- 打印状态数据 print(info.status_id, "==", status_id) -- 如果玩家有这个状态了,就不是新状态 if info.status_id == status_id then new_status = nil break end end
- !!! bug消失了 !!!
- 这就遇到玄学了,难道还加个打印就能改bug?
- 难道是量子编程? 观测者效应,打印参数,还能改变数据
- 重复几次打印数据,与去除打印数据
-
- 打印数据, !!! bug消失 !!!
-
- 去除打印, !!! bug复现 !!!
-
- 觉得有些可怕
- 一下子不懂 lua 代码了
- 尝试在判断状态id是否相等的地方增加else,增加断言数据
for i, info in ipairs(target_status) do -- 如果玩家有这个状态了,就不是新状态 if info.status_id == status_id then new_status = nil break else print("error--- ", info.status_id == status_id, info.status_id, status_id, for_i) assert(not (info.status_id == status_id)) end
- !!! 断言报错了 !!!
- 断言发现 状态id 确实相等,可能如果相等不应该能走入else部分
- 开始准备从我们的源代码中提取最小可复现的用例
- 我们的项目使用 c++ 和 lua, 并且有好几千个lua文件,提取过程十分缓慢
- 提取用例,提交报告
- 第二天作者说修复了
- 编译最新版的 LuaJIT
- 还是会出现 bug, 出现的概率变成非常低
- 继续缩减最小可复现的用例
- 继续提交可复现的用例
- 又过了一周,作者又提交了新的bug修复
- 说遗漏了我编译 LuaJIT 的参数
-
一波三折的bug终于修复了