2010-05-19 70 views
0

我有一個程序,我只是改變了使用boost :: multi_index_container集合。在完成了這些工作並在調試模式下測試了我的代碼後,我對自己感覺非常好。在發佈模式下增強multi_index_container崩潰

但是,然後我編譯了NDEBUG集的發佈版本,代碼崩潰了。不是馬上,但有時在單線程測試中,通常在多線程測試中。

分段錯誤發生在boost索引更新的內部和旋轉與索引更新相關的函數,並且它們發生的原因是節點具有NULL左和右指針。

我的代碼看起來有點像這樣:

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); 
    } 
} 

回答

1

我知道答案時,我張貼的問題,但我想我會分享這個每個人的薰陶。當我自己爲他們搜索時,我沒有找到任何答案,所以我必須自己弄清楚。

我可以看到其他程序員很容易陷入同一陷阱。

問題是在我的代碼中的update_hint。它被下一個register_update呼叫使用。通常情況下,這很有效。

但是!

調用replace後使用插入提示會導致插入提示無效!出於某種原因,它大部分時間都工作,似乎總是在調試模式下工作。在某些情況下,Boost似乎在發佈模式下使用了未檢查的提示,儘管如此,事實證明這是殺手。

+0

一旦你把你的時間,想想看這是非常微不足道的。 'replace'只不過是'erase' +'insert'的語法糖,可能會有一些加速,因此迭代器無效(因爲它的指針被刪除)。用map('ordered_unique')這樣做會產生相同的行爲。遺憾的是,圖書館沒有提供「檢查迭代器」,它會在你的調試時間內得到方便! – 2010-05-20 06:45:24

+0

@Matthieu:是的,擦除並插入。這很明顯,當你考慮它。但是,因爲我正在替換以前使用STL映射的代碼,並直接修改了關鍵衝突的映射值,所以我的大腦完全通過了這個問題。 – 2010-05-20 19:16:47

0

我認爲你的自我回答是不正確的。在所有情況下,replace保留update_hint的有效性(參見docs)。實際上,這個操作是而不是,作爲一個刪除後跟一個插入(如@Matthieu所建議的),但比這更聰明(替換是在適當的位置)。

檢查你的代碼,很容易證明,如果update_hint是一個有效的迭代時被調用register_update,它將執行後仍然有效:insert總是返回一個有效的(和提領)迭代器,並replace不更改或無效update_hint。所以,唯一的可能性是update_hint無效外部register_update。可能的原因:

  1. 元素update_hint點在Implementation代碼刪除別處。
  2. 您沒有正確初始化update_hint,其有效值爲Implementation施工時間。

HTH

相關問題