2015-08-26 69 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