在发布模式下提升multi_index_container崩溃

时间:2010-05-19 23:52:33

标签: c++ boost

我有一个程序,我刚刚改为使用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);
    }
}

2 个答案:

答案 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>}之外无效。可能的原因:

  1. 指向的register_update元素在update_hint代码中的其他位置被删除。
  2. Implementation施工时,您没有使用有效值正确初始化update_hint
  3. HTH