C++ 在释放模式下提升多索引容器崩溃

C++ 在释放模式下提升多索引容器崩溃,c++,boost,C++,Boost,我有一个程序,我刚刚改为使用boost::multi_index_容器集合。在我这样做并在调试模式下测试了我的代码之后,我对自己感觉很好 然而,随后我用NDEBUG集编译了一个发布版本,代码崩溃了。不立即,但有时在单线程测试中,通常在多线程测试中 分段错误发生在与索引更新相关的boost insert和rotate函数的内部深处,它们的发生是因为节点具有空的左指针和右指针 我的代码看起来有点像这样: struct Implementation { typedef std::pair<

我有一个程序,我刚刚改为使用boost::multi_index_容器集合。在我这样做并在调试模式下测试了我的代码之后,我对自己感觉很好

然而,随后我用NDEBUG集编译了一个发布版本,代码崩溃了。不立即,但有时在单线程测试中,通常在多线程测试中

分段错误发生在与索引更新相关的boost insert和rotate函数的内部深处,它们的发生是因为节点具有空的左指针和右指针

我的代码看起来有点像这样:

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);
    }
}
struct实现{
typedef std::pair update\u pair\u type;
结构监视{};
结构更新{};
typedef boost::多索引容器<
更新\u对\u类型,
boost::多索引::按索引索引<
boost::多索引::有序唯一<
boost::multi_index::tag,
boost::multi_index::member
>,   
boost::多索引::有序非唯一<
boost::multi_index::tag,
boost::multi_index::member
>    
>    
>更新地图类型;
typedef std::vectorupdate\u list\u type;
更新地图类型更新地图;
更新映射类型::迭代器更新提示;
无效寄存器更新(uint32\u t监视、uint32\u t更新);
无效do_更新(uint32_t开始,uint32_t结束);
};
无效实现::寄存器更新(uint32\u t监视、uint32\u t更新)
{
更新\u对类型新的\u对(监视\u偏移,更新\u偏移);
更新提示=更新映射。插入(更新提示,新的提示对);
如果(更新提示->秒!=更新偏移量){
bool replaced\u unused\uu=update\u map.replace(更新\u提示,新的\u对);
断言(替换);
}
}

当我发布这个问题时,我知道答案,但我想我会分享这一点,供大家启发。我自己在谷歌上搜索的时候没有找到任何答案,所以我必须自己找出答案

我可以看到其他程序员很容易落入同样的陷阱

问题在于我的代码中的
update\u提示
。它被下一次
register\u update
调用使用。通常情况下,这种方法非常有效

但是


调用
replace
后使用插入提示会导致插入提示无效!出于某种原因,它大部分时间都在工作,而且似乎总是在调试模式下工作。Boost似乎在发布模式编译的某些情况下使用了未经检查的提示,结果证明这是致命的。

我认为您的自我回答是错误的<代码>替换在所有情况下保留
更新提示
的有效性(请参阅)。事实上,这个操作并不是以先擦除后插入的方式实现的(正如@Matthieu所建议的那样),而是更聪明的方式实现的(替换是在适当的地方完成的)

检查您的代码,很容易证明,如果调用
register\u update
update\u hint
是一个有效的迭代器,那么它在执行后将保持有效:
insert
始终返回一个有效(且可取消引用)的迭代器,
replace
不会更改或使
update\u hint
无效。因此,唯一的可能性是
update\u hint
register\u update
之外无效。可能的原因:

  • update\u hint
    指向的元素在
    实现中的其他地方被删除
  • 实现
    构造时,没有使用有效值正确初始化
    更新提示

  • HTH

    只要你慢慢想一想,它就相当微不足道了
    replace
    不过是
    erase
    +
    insert
    的语法糖,可能有一些加速,因此迭代器无效(因为它的指针被删除)。使用映射(
    ordered_unique
    )执行此操作将产生相同的行为。遗憾的是,该库没有提供“已检查迭代器”,它在调试期间会很方便@马修:是的,擦除并插入。当你考虑时,这是显而易见的。然而,因为我正在替换以前使用STL映射的代码,并且直接修改了键碰撞的映射值,所以我的大脑完全忽略了这个问题。