2015-08-26 67 views
2

我的程序似乎在將一個int插入到一個集合時崩潰了,我無法追查這個原因。這裏是有相關代碼:當插入一組int時崩潰

bool request::check_list(std::vector<int> search_vec) 
{ 

    std::set<int> *tmp_ptr = create_int_set(); 
    boost::shared_ptr<std::set<int> > c_list(tmp_ptr); 


    if(aerospike_query_foreach(as, &err, NULL, &query, process_set, &c_list) != AEROSPIKE_OK) 
    { 
     return false; 
    } 

    for(int i = 0; i < search_vec.size(); i++) 
    { 
     if(c_list->find(search_vec[i]) != c_list->end()) 
     { 
      c_list_value_ = search_vec[i]; 
      return true; 
     } 
    } 
    return false;  
} 

bool request::process_set(const as_val *val, void * udata) 
{ 
    try 
    { 
     boost::shared_ptr<std::set<int> > c_set = *(boost::shared_ptr<std::set<int> > *)(udata); 
     if(val == NULL) 
     { 
      return true; 
     } 
     if(val->type == AS_REC) 
     { 
      if (val!=NULL) 
      { 
       as_record *rec = as_record_fromval(val); 

       if (rec!=NULL) 
       { 
        as_integer* c_id = as_record_get_integer(rec,"c_id"); 
        int cid = 0; 
        cid = boost::lexical_cast<int>(c_id->value); 
        if(c_set != nullptr) 
        { 
         c_set->insert(c_id); 
        } 
        as_record_destroy(rec); 
        as_integer_destroy(c_id); 
       } 
     } 
     return true; 
    }catch(...){} 
    return false; 
} 

c_set->insert(c_id);導致段錯誤。這是這次崩潰的回溯:

#0 0x00007f2064299f94 in std::_Rb_tree_rotate_right(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&)() from /usr/lib64/libstdc++.so.6 
#1 0x00007f206429a12b in std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)() from /usr/lib64/libstdc++.so.6 
#2 0x00000000004829d9 in std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>, std::allocator<int> >::_M_insert_<int const&> (this=0x7f1fcc005440, __x=0x0, __p=0x7f1f3c0009a0, [email protected]) 
    at /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_tree.h:981 
#3 0x000000000047f1e0 in std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>, std::allocator<int> >::_M_insert_unique<int const&> (this=0x7f1fcc005440, [email protected]) 
    at /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_tree.h:1299 
#4 0x000000000047c473 in std::set<int, std::less<int>, std::allocator<int> >::insert (this=0x7f1fcc005440, [email protected]) 
    at /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_set.h:415 
#5 0x00000000004765ee in request::process_set (val=0x7f20159e73e0, udata=0x7f200b9d6620) at ../../request.cpp:1862 

我假設有一個問題,其中該集沒有被初始化,或類似的東西。這是我如何創建並從另一個函數,我試圖通過這組兩種方式來創建它:

boost::shared_ptr<std::set<int> > c_list(new std::set<int>()); 

std::set<int> *tmp_ptr = create_int_set(); 
boost::shared_ptr<std::set<int> > c_list(tmp_ptr); 

std::set<int>* request::create_int_set() 
{ 
    return new std::set<int>(); 
} 

調用函數是一個回調函數從數據庫驅動程序,這需要在幾個不同的對象,最顯着的卻是process_set和c_list,這是作爲一個void *傳遞:

aerospike_query_foreach(as, &err, NULL, &query, process_set, &c_list) 

這個崩潰不會發生的事情,其實它是相當RA這讓我覺得我做錯了一些不明確的行爲。任何幫助將不勝感激!

+4

聽起來像是一生的問題。儘管如此,我們沒有辦法用這些小隔離片段來做。你的[testcase](http://stackoverflow.com/help/mcve)在哪裏? –

+0

我會在一分鐘內更新更多的流程,但並沒有更多。但希望額外的代碼會給你一個更好的主意。 – Eumcoz

+6

將'void *'投射到'shared_ptr *'的這一行將震顫我的脊柱。我不知道這是錯誤的,但我建議將'c_list.get()'發送到'aerospike_query_foreach'並在'process_set'函數中使用原始的'std :: set '指針;它聲稱沒有所有權/共享似乎不是線程/可重入的,所以它應該是安全的。 (至少,嘗試消除引用計數錯誤...) –

回答

3

aerospike APi documentation說回調(即process_set(),這裏):

執行查詢,並呼籲每個結果項的回調函數。 多個線程可能會並行調用回調。 因此,你的回調實現應該是線程安全的。

由於多個線程可能在同一時間在同一組插入(在一個由共享指針所指向的),你會得到競爭條件,因此不確定的行爲!

所以我認爲你應該保護至少你的設置插入塊與lock_guard在互斥體上。

重要編輯:boost::shared_ptr<>can't assumed to be thread safe。在boost.org的例子中,他們建議一個超出範圍的共享指針可能會導致競爭。因此,強烈建議在註釋中遵循Matthew Moss的建議,並在process_set()的範圍內使用指向該集合的原始指針。

+1

謝謝Christophe,也許就是這樣,我會在插件周圍插入一個互斥體,看看是否能解決這個問題,我應該首先檢查Aerospike文檔。對於那個很抱歉。 – Eumcoz

+0

我建議使用ThreadSanitizer或valgrind之類的工具來確認問題。 – edmz

+1

@Eumcoz不幸的是,插入塊周圍的互斥量可能不足。查看編輯。 – Christophe