ошибки seg из-за многопоточности (с использованием библиотек повышения)

У нас есть программа, которая использует как матрицу boost, так и библиотеки разреженных матриц, и мы пытаемся интегрировать потоки boost. Однако при переходе от однопоточного к многопоточному приложению возникают ошибки сегментации, которые не возникают в случае однопоточного приложения.

Мы провели отладку с помощью gdb (в Eclipse), и я обнаружил, что ошибки seg возникают во время вызовов функций в коде повышения, т.е. я пытаюсь получить доступ к записи разреженной матрицы, а трассировка стека переходит в код повышения и умирает в какая-то точка (не всегда одна и та же точка) в этих файлах.

Я запутался, потому что эти матрицы распределены в отдельных потоках, а все общие ресурсы защищены блокировками мьютексов. Кроме того, я не думал, что многопоточность часто вызывает ошибки сегментации, а просто множественный доступ и неверные данные. Однако я, очевидно, не разбираюсь в многопоточном программировании, поэтому я надеялся, что кто-то, более опытный в этой области, сможет дать несколько советов.

Я использую управляемую систему make с ускорением, и пример команды компиляции:

g++ -DNDEBUG -I"/usr/local/include/boost-1_38" -I/usr/local/include -I"/home/scandido/workspace/BigSHOT/src" -I"/home/scandido/workspace/BigSHOT/src/base" -O3 -Wall -c -fmessage-length=0 `freetype-config --cflags` -pthread -MMD -MP -MF"src/utils/timing_info.d" -MT"src/utils/timing_info.d" -o"src/utils/timing_info.o" "../src/utils/timing_info.cpp"

и команда компоновщика

g++ -L"/usr/local/lib" -L/usr/local/lib -o"BigSHOT"  ./src/utils/timing_info.o ... many more objects ... ./src/base/pomdp/policy_fn/EventDriven.o ./src/base/pomdp/policy_fn/Greedy.o  ./src/anotheralgorithm.o   -lboost_serialization-gcc43-mt -lpthread -lboost_thread-gcc43-mt -lboost_program_options-gcc43-mt -lboost_iostreams-gcc43-mt -lpng -lpngwriter -lz -lfreetype

Вот трассировка стека для потока, в котором произошел сбой сегментации:

Thread [5] (Suspended: Signal 'SIGSEGV' received. Description: Segmentation fault.) 
    17 boost::numeric::ublas::mapped_matrix<bool, boost::numeric::ublas::basic_row_major<unsigned long, long>, boost::numeric::ublas::map_std<unsigned long, bool, std::allocator<std::pair<unsigned long const, bool> > > >::operator() /usr/local/include/boost-1_38/boost/numeric/ublas/matrix_sparse.hpp:377 0x000000000041c328 
    16 BigSHOT::Fire1FireState::get_cell() /home/scandido/workspace/BigSHOT/src/systems/fire1/pomdp/Fire1State.cpp:51 0x0000000000419a75    
    15 BigSHOT::Fire1SquareRegionProbObsFn::operator() /home/scandido/workspace/BigSHOT/src/systems/fire1/obs_fn/Fire1SquareRegionProbObsFn.cpp:92 0x000000000042ac37   
    14 BigSHOT::Fire1SquareRegionProbObsFn::operator() /home/scandido/workspace/BigSHOT/src/systems/fire1/obs_fn/Fire1SquareRegionProbObsFn.cpp:66 0x000000000042a8bf   
    13 BigSHOT::BayesFilterFn<BigSHOT::Fire1Belief, BigSHOT::Fire1State, BigSHOT::Fire1Action, BigSHOT::Fire1Observation>::update() /home/scandido/workspace/BigSHOT/src/base/pomdp/filter_fn/BayesFilterFn.h:50 0x0000000000445c3b 
    12 BigSHOT::HyperParticleFilter<BigSHOT::Fire1Belief, BigSHOT::Fire1Action, BigSHOT::Fire1Observation>::future_evolution() /home/scandido/workspace/BigSHOT/src/base/hpf/HyperParticleFilter.h:127 0x00000000004308e0   
    11 BigSHOT::HyperParticleFilter<BigSHOT::Fire1Belief, BigSHOT::Fire1Action, BigSHOT::Fire1Observation>::hyperfilter() /home/scandido/workspace/BigSHOT/src/base/hpf/HyperParticleFilter.h:86 0x000000000043149b 
    10 BigSHOT::HyperParticleFilterSystem<BigSHOT::HyperCostFn<BigSHOT::Fire1Belief, BigSHOT::Fire1Action>, BigSHOT::PolicyFn<BigSHOT::Fire1Belief, BigSHOT::Fire1Action>, BigSHOT::Fire1Belief, BigSHOT::Fire1Action, BigSHOT::Fire1Observation>::next_stage() /home/scandido/workspace/BigSHOT/src/base/hpf/HyperParticleFilter.h:189 0x0000000000446180  
    9 hyperfilter() /home/scandido/workspace/BigSHOT/src/anotheralgorithm.cpp:126 0x0000000000437798    
    8 hf_thread_wrapper() /home/scandido/workspace/BigSHOT/src/anotheralgorithm.cpp:281 0x0000000000437cd9  
    7 boost::_bi::list1<boost::_bi::value<int> >::operator()<void (*)(int), boost::_bi::list0>() /usr/local/include/boost-1_38/boost/bind.hpp:232 0x000000000043f25a    
    6 boost::_bi::bind_t<void, void (*)(int), boost::_bi::list1<boost::_bi::value<int> > >::operator() /usr/local/include/boost-1_38/boost/bind/bind_template.hpp:20 0x000000000043f298 
    5 boost::detail::thread_data<boost::_bi::bind_t<void, void (*)(int), boost::_bi::list1<boost::_bi::value<int> > > >::run() /usr/local/include/boost-1_38/boost/thread/detail/thread.hpp:56 0x000000000043f2b6   
    4 thread_proxy()  0x00007f28241c893f    
    3 start_thread()  0x00007f28243d93ba    
    2 clone()  0x00007f2822a4ffcd   
    1 <symbol is not available> 0x0000000000000000  

Строка кода, где это происходит, является второй в этом блоке:

const_reference operator () (size_type i, size_type j) const {
  const size_type element = layout_type::element (i, size1_, j, size2_);
  const_subiterator_type it (data ().find (element));

Я хотел бы повторить, что ошибка seg не всегда возникает в одном и том же месте кода, а всегда при выполнении чего-то в коде повышения.

Заранее спасибо за вашу помощь!


person RandomGuy    schedule 28.08.2009    source источник
comment
Начните с того, что убедитесь, что все ваше приложение скомпилировано с использованием параметра -pthread для компилятора. Каждый объектный файл. Если сбой все еще существует, опубликуйте фактическую обратную трассировку.   -  person Vladimir Prus    schedule 29.08.2009
comment
Я думаю, что у меня есть правильные варианты компиляции, но я не уверен. -pthread находится там. Я добавил образцы в текст вопроса, он выглядит правильно?   -  person RandomGuy    schedule 30.08.2009
comment
Я также добавил трассировку стека. Спасибо.   -  person RandomGuy    schedule 30.08.2009


Ответы (1)


Segfault может появиться из-за других, хорошо отлаженных библиотек (или даже из стандартной библиотеки!), если вы повреждаете кучу или свободное хранилище, например, путем двойного освобождения (или двойного удаления) указателя, доступа к указателю, который был уже освобожден (или удален), освобождение (или удаление) указателя, который не был выделен, использование удаления там, где вы должны были использовать удаление [] или наоборот, и т. д.

Этот сбой часто происходит в совершенно другом месте и в совершенно другое время, чем когда и где произошла ошибка. Если у вас есть переменные, отличные от матриц, совместно используемых несколькими потоками, и у вас есть состояние гонки, которое, например, заставляет вас дважды удалить общую переменную, это может повредить свободное хранилище, а затем вызвать сбой внутри матрицы повышения. код.

Вы должны запустить свой код с помощью инструмента, такого как valgrind, чтобы попытаться отследить повреждение кучи/свободного хранилища.

person Tyler McHenry    schedule 29.08.2009
comment
Спасибо за предложения. Мы используем shared_ptr (умный указатель) boost, поэтому я вполне уверен, что проблема не в неправильном удалении памяти. (В многопоточном коде нет операторов удаления.) У нас есть только один объект, совместно используемый потоками, и мы обращаемся к нему только в начале и конце потоков, чтобы копировать данные и записывать их обратно. Мы используем блокировки для предотвращения одновременного доступа. между нитями. Есть ли что-то, что я не рассматриваю здесь? - person RandomGuy; 30.08.2009
comment
Я никогда раньше не использовал valgrind. Можете ли вы предложить хороший учебник для начала работы помимо документации на их сайте? - person RandomGuy; 30.08.2009
comment
valgrind довольно прост в использовании; это понимание вывода, что иногда является проблемой. Все, что вам действительно нужно сделать, чтобы начать работу с такой программой, это скомпилировать ее с символами отладки, а затем запустить: valgrind --tool=memcheck ./yourapp. Для каждой ошибки доступа к памяти он сообщит, где она произошла, что это была за ошибка, а затем предоставит вам одну или две сокращенные трассировки стека, которые показывают, где произошли несовместимые операции. К сожалению, насколько я знаю, нет лучшего ресурса, чем их официальные документы. Взгляните на раздел memcheck, так как это то, что вам нужно. - person Tyler McHenry; 30.08.2009
comment
Кажется, вы правы. После удаления всего плохого, на что мне обратил внимание valgrind, ошибка seg, похоже, исчезла. Спасибо за вашу помощь! - person RandomGuy; 31.08.2009