STL中的容器map:不要用指针做键值

我不知道会不会有人跟我犯同样的错误。我只能说,这个bug实在太奇葩了。


这两天在跑trace时发现,同样的参数下重复运行,第一次的数据总是跟后面几次有很大出路。一开始觉得是随机数的关系,但心里总有些不安。试着重复运行了10次,果然第一次跟后面9次的数据有明显不同,delivery rate大概有5%的差距。

于是我怀疑会不会是结果之间有干涉,例如用来保存结果的数组之间由于编码的问题互相干扰。但反复的检查过后,确定不是这方面的问题。

接下来开始检查随机数的问题。在程序中有两个地方用到了随机数,一个是source node的选择,一个是interests的产生。(专门研究了一下随机数的机制,调用了srand()之后随机数的计算会重启)在这两个地方设置了srand(1),也就是控制trace的每次执行,随机数序列是一样的,但问题依旧。

这说明在某个地方仍然存在不可控制的因素。然后开始检查helpful类。这个类是node的一个子类,表示所有node的行为是合作的策略。试着注释掉connect函数中缓存电影的部分,出人意料的事情发生了,这次所有的数据是一致的。

但问题仍然没有解决,因为不明白为什么会出现这样的情况。试着按时间轴输出每个session中的message,这次终于发现了疑点。照理说在控制随机数的情况下,每次执行时同一个session中的message应该是相同的,但呈现的结果却是,message是相同的,排列却不同。

这下终于发现了问题所在。因为需要message同持有者的映射关系,我用一个map容器来存一个session中所有的message与其持有者。但在实现的时候,为了方便,我用指向message的指针来作为map的键值。这在逻辑上没有什么问题,不同的message的指针自然是不同的。但由于map的实现机制,这有给程序带来了不可控制的因素。在map中,所有的元素对会按键值有序排列,因此,用指针作键值的话,message就会按指针的大小排列,而指针的值却是不可控制的。而我在构建了map之后,使用迭代器按其默认排序输出了所有的message。这就导致了在重复运行多次时,指针的变化导致多次运行的数据有较大出入。

找出这个bug后整个人郁闷得要吐血,根本没想到图省事的一个小小举动导致了这么大的问题。虽然说在跑trace时需要随机化的结果,但这个随机应该是可控制的。还好前两天顺手翻了STL源码剖析,不然这个原因也悟不出来。


最后不知道应该吐槽什么。只能说,不能把STL当做黑盒来用;安全起见,不要用指针作map的键值!

你可能感兴趣的:(C++)