代码之家  ›  专栏  ›  技术社区  ›  Zan Lynx

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

  •  0
  • Zan Lynx  · 技术社区  · 15 年前

    我有一个程序,我刚刚改为使用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);
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  1
  •   Zan Lynx    15 年前

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

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

    问题在于 update_hint 在我的代码中。它被下一个用户使用 register_update 呼叫通常情况下,这很有效。

    但是

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

        2
  •  0
  •   Joaquín M López Muñoz    10 年前

    我认为你的自我回答是错误的。 replace 保留的有效性 update_hint 在所有情况下(参见 docs ).事实上,这次行动 实现方式是先擦除,然后插入(正如@Matthieu所建议的),但更聪明的是(替换已到位)。

    检查你的代码,如果 更新提示 register_update 调用时,它将在执行后保持有效: insert 总是 返回有效(且可取消引用)迭代器,然后 代替 不会改变或失效 更新提示 .所以,唯一的可能性是 更新提示 无效 外部 注册更新 .可能的原因:

    1. 元素 更新提示 指向的点在中的其他地方被删除 Implementation 密码
    2. 你没有正确初始化 更新提示 有效值为 实施 施工时间。