初始化惹的祸

我们某种业务,客户端获取服务端数据,有重试机制。其中重试的timer原定是可配置的,就是服务端改了数值,客户端与服务端交互消息之后就起效。

客户端版本发布之后,发现客户端一直按默认值执行,更改timer的配置无效。

同事debug后,发现消息在从服务端发出去之前就不对了。获取配置后给消息赋值时打出来的timer的数值是正确的,序列化后再发送出去之前再打出来就不对了。代码逻辑看起来完全正确...

后来我也把代码拿过来看,逻辑咋看也没什么破绽。研究了一会儿之后,才恍然大悟。


C++的结构体或是类(C++中struct就是class),咱们提倡要对成员初始化,以避免忘记初始化带来的各种意外行为。这个实践中已经碰到多次这样的问题了。

这个代码就遵循这种编程好习惯,在消息的结构体写了构造函数,然后对一个map(STL的map)成员作了初始化,若干个key对应的value都赋了默认值。

解包,也就是反序列化,的时候,用inserter()获得map的插入迭代器然后把数据从buffer中取出插入到消息类的map成员中。


这里就杯具了。以前的类似的代码使用inserter没问题,可以正确地从buffer里头解出数据放到map中。现在这个消息类,写了构造函数,对map做了初始化,map中的几个key都赋了值了。反序列化的时候对inserter

inserter()返回该map的一个insert_iterator,而从STL源码可以看到insert_iterator的赋值是这么实现的:


  operator=(const typename _Container::value_type& __value) { 
    iter = container->insert(iter, __value);
    ++iter;
    return *this;
  }


在我们这场景中,最后变成map::insert()操作。而map::insert()会检查插入的key是否存在,存在就什么都不做。这里,解包的时候,消息类实例化已经在构造函数中插入几个key到map成员中(赋为默认配置值),因此反序列化时map::insert()因key已存在 所以消息对象仍保留的默认值。


老的代码使用inserter()一点问题都没有,因为没对map做任何初始化....

注意初始化了反而惹出问题:)


当然,不是说这个初始化不好。其实主要是inserter()以及map::insert()有点陷阱,可能行为不是写的人预期那样。其实前一阵另外一份代码刚刚发现一个bug是使用map::insert()没有覆盖旧的value引起。




-------------------------------------------------------------------------------------------------

更多博文请订阅RSS,更多微博请关注@千里孤行Nerd



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值