我有一个程序,我刚刚改为使用boost :: multi_index_container集合。在我这样做并在调试模式下测试我的代码之后,我对自己感觉非常好。
但是,然后我用NDEBUG集编译了一个发布版本,代码崩溃了。不是立即,但有时在单线程测试中,通常在多线程测试中。
分段错误发生在boost插入和旋转与索引更新相关的函数深处,并且它们正在发生,因为一个节点有左右指针。
我的代码看起来有点像这样:
struct Implementation {
typedef std::pair<uint32_t, uint32_t> update_pair_type;
struct watch {};
struct update {};
typedef boost::multi_index_container<
update_pair_type,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::tag<watch>,
boost::multi_index::member<update_pair_type, uint32_t, &update_pair_type::first>
>,
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<update>,
boost::multi_index::member<update_pair_type, uint32_t, &update_pair_type::second>
>
>
> update_map_type;
typedef std::vector< update_pair_type > update_list_type;
update_map_type update_map;
update_map_type::iterator update_hint;
void register_update(uint32_t watch, uint32_t update);
void do_updates(uint32_t start, uint32_t end);
};
void Implementation::register_update(uint32_t watch, uint32_t update)
{
update_pair_type new_pair( watch_offset, update_offset );
update_hint = update_map.insert(update_hint, new_pair);
if( update_hint->second != update_offset ) {
bool replaced _unused_ = update_map.replace(update_hint, new_pair);
assert(replaced);
}
}
答案 0 :(得分:1)
当我发布问题时,我知道答案,但我想我会分享这个以供每个人的启发。我自己用Google搜索时没有找到任何答案,所以我必须自己解决这个问题。
我可以看到其他程序员很容易陷入同一个陷阱。
问题在于我的代码中的update_hint
。它将在下一个register_update
电话中使用。通常这很有效。
<强> BUT!强>
在调用replace
后使用插入提示会导致插入提示无效!由于某种原因,它大部分时间都可以工作,并且似乎总是在调试模式下工作。在某些情况下,Boost似乎在发布模式编译中使用了未经检查的提示,但结果却是杀手。
答案 1 :(得分:0)
我认为你的自我回答是不正确的。在所有情况下,replace
都会保留update_hint
的有效性(请参阅docs)。事实上,这个操作不实现为删除后插入(如@Matthieu所建议的那样),但比这更聪明(替换已经完成)。
检查代码时,很容易证明,如果update_hint
在调用register_update
时是一个有效的迭代器,它将在执行后保持有效:insert
始终< / em>返回一个有效(和可解除引用)的迭代器,replace
不会更改或使update_hint
无效。因此,唯一的可能性是update_hint
在 {/ 1>}之外无效。可能的原因:
register_update
元素在update_hint
代码中的其他位置被删除。Implementation
施工时,您没有使用有效值正确初始化update_hint
。HTH