遍历删除
Posted *蚂蚁*
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遍历删除相关的知识,希望对你有一定的参考价值。
今天想实现个小功能:战斗结束时,后台先立即退房间
-
退房间逻辑包含了:所有人退光后,销毁房间
-
销毁房间,会同步销毁GameWorld
在OnPlayerDie回调中加了一句代码,导致连续出现四处宕机bug~太牛逼了
-
Bug分属四处不同模块
-
均是同种原因:遍历中途,删元素,上层持有的引用失效
很好修复,但这不是重点。重点是,这bug同时隐匿在
-
系统最底层,碰撞检查器,遍历调用OnTriggerEnter
-
OnTriggerEnter 参数中的某些对象已被销毁
-
系统底层,GameWorld update
-
系统底层,GameWorld内置计时器
-
GameWorld都没了,还在跑遍历
-
业务层,OnPlayerDie遍历队伍,通知调用链中,触发退队,迭代器失效
分别不同人写的模块,且不做本次业务改动,跑得很稳定
-
也就是说:在写模块时,开发者都没想到这bug。这里有两层缘故:
-
一是,迭代遍历,太常见,太顺手了 …… 依赖个人警惕,非常不靠谱
-
交叉review靠谱点,但现实里review是需要成本的,极少团队愿意支付这个成本
-
二是,上述模块均带回调事件
-
回调链,究竟多长,会做啥 …… 不受起初写该模块人的控制
-
是个需求上就非内聚的东西
本质是:持有着某对象的引用,调用事件函数后,共享出去了它的操作权,但写的人忘了它会被改,更不能期望别人会主动通知。
根本解决方案:支持一套迭代安全的容器模板,仅高内聚的模块允许使用原生迭代器
-
预想的坑:回调链中,可能再次调用到遍历(函数重入),常规类中记个游标的方式,也是不安全的
【扩展联想】
-
析构比构造难多了
-
c艹的确定性析构,需要开发者准确掌握资源回收的时序
-
业务层的资源回收步骤,往往带着很长的调用链
-
写这个,有种网上描述屎山代码的体验~改个小地方,崩一片
-
如若是线上版本开发,做这个的程序,会是啥心态
-
作为管理者,你会悉心了解问题本质,企图改掉它们吗?大概率不会
-
完整解决它的可能性极低,大约会搞成延时删除、拷贝遍历之类的
-
不解决根本问题,下一个不注意的仍会踩坑 …… 避开坑,而不是填坑
-
c++是个很棒的语言,但得重新审视下它做业务开发的性价比
-
其它语言碰见这bug的印象淡许多
-
c# foreach 遍历删会报容器被修改的异常
-
go for range 删不会报错
-
带gc的语言,这方面表现好得多。但一样有坑点
-
比如遍历中途加元素,引发扩容
-
你还在遍历的,仍是老的内存块,老的元素
以上是关于遍历删除的主要内容,如果未能解决你的问题,请参考以下文章