STL中的容器map:不要用指针做键值
2012-11-04 20:26
218 查看
我不知道会不会有人跟我犯同样的错误。我只能说,这个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的键值!
这两天在跑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的键值!
相关文章推荐
- STL之红黑树容器:set,hash_set,multiset,hash_map,multimap
- C++STL库中map容器常用应用
- STL容器 list、vector、map、set 使用的陷阱
- STL学习之map容器-insert
- STL容器(四)——hash_map
- C++ STL关联容器 set和map学习笔记
- STL 笔记(二) 关联容器 map、set、multimap 和 multimap
- STL学习系列九:Map和multimap容器
- c++中map容器简单功能实现测试附带结构体指针测试
- STL中的map容器的一点总结
- STL中map容器的元素插入
- STL学习(一)map容器学习(三)-multimap
- STL之关联容器(set /map /multiset /multimap)
- STL容器(二)——map
- STL — map容器用法的详解
- STL_MAP容器常用操作
- C++ STL 中 map 容器的说明和使用技巧
- stl容器的区别:vector list deque set map-底层实现
- 【C++】STL常用容器总结之八:映射map
- STL容器里存放对象还是指针(原)