Кажется, что моя программа падает при вставке и 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);
вызывает segfault. Вот этот след падения:
#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, __v=@0x7f20159e729c)
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, __v=@0x7f20159e729c)
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, __x=@0x7f20159e729c)
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)
Этот сбой не происходит все время, на самом деле он довольно редкий, что заставляет меня думать, что я что-то не так делаю, какое-то неопределенное поведение. Любая помощь будет принята с благодарностью!
Aerospike APi документация говорит для обратного вызова (т.е. process_set()
, Вот):
Выполните запрос и вызовите функцию обратного вызова для каждого элемента результата.
Несколько потоков, вероятно, будут вызывать обратный вызов параллельно.
Следовательно, Ваша реализация обратного вызова должна быть поточно-ориентированной.
Поскольку несколько потоков могут вставляться одновременно в один и тот же набор (на который указывает ваш общий указатель), вы получите условия гонки и, следовательно, неопределенное поведение!
Поэтому я думаю, что вы должны защитить по крайней мере ваш блок вставки набора с lock_guard
на мьютексе.
Важное редактирование: boost::shared_ptr<>
не может считаться потокобезопасным. В примерах на boost.org они предполагают, что общий указатель, выходящий из области видимости, может вызвать гонку. Поэтому очень рекомендуется следовать Мэтью Мосспредложите в комментариях и используйте необработанный указатель на множество в рамках process_set ().