boost :: thread: Segfault при запуске оптимизированной версии - PullRequest
3 голосов
/ 21 февраля 2009

У меня проблемы с получением boost:thread на работу. Работает нормально при компиляции без оптимизации:

g++ -o test-thread test-thread.cpp -lboost_thread-gcc-mt-s -lpthread
./test-thread

Но версия, скомпилированная с оптимизацией, вылетает

g++ -O2 -o test-thread test-thread.cpp -lboost_thread-gcc-mt-s -lpthread
./test-thread
Segmentation fault

Кто-нибудь знает, в чем может быть причина?

Вот код, который я использую:

#include <boost/thread.hpp>
#include <boost/function.hpp>

void task1() {
  // do something
}
void task2() {
  // do something
}

int main (int argc, char ** argv) {
  using namespace boost;

  function0<void> f1(&task1);
  function0<void> f2(&task2);

  thread thread_1(f1);
  thread thread_2(f2);

  // do other stuff 
  thread_2.join();
  thread_1.join();
  return 0;
}

P.S .: Я использую Boost 1.32 на Ubuntu Linux.

UPDATE:

Здесь происходит сбой в отладчике (где строка 37 - это строка с thread_2.join(); в моем исходном коде):

(gdb) bt
#0  0x080499e0 in boost::thread::join ()
#1  0x080496b8 in main (argc=1, argv=0xbfea3eb4) at ../src/test-thread.cpp:37

Вот мои настоящие две функции:

void task1() {
  std::cerr << "THREAD 1 START" << std::endl;
  for(double i=0; i<999999; ++i){
    std::cout << i << std::endl;
  }
  std::cerr << "THREAD 1 END" << std::endl;
}

void task2() {
  std::cerr << "THREAD 2 START" << std::endl;
  for(double i=0; i<999999; ++i){
    std::cout << i << std::endl;
  }
  std::cerr << "THREAD 2 END" << std::endl;
}

Спасибо за любую помощь!

Ответы [ 2 ]

3 голосов
/ 21 февраля 2009

Не могли бы вы убедиться, что дампы ядра активны (ulimit -c unlimited), скомпилировать с символами (-O2 -g), запустить и открыть трассировку стека в gdb? (gdb test-thread core, затем введите backtrace в приглашении gdb, quit для выхода)

UPDATE

На основании обратной трассировки ошибка сегментации происходит в boost::thread::join. Можешь ли ты заново откройте ядро ​​и:

  • получить разборку по методу boost::thread::join:
    • disassemble boost::thread::join
    • disassemble
  • получить дамп регистров:
    • info registers

Реализация boost::thread::join (повышение 1,32 официальный источник) довольно прямолинейно, так что если только Ubuntu двоичные файлы сильно расходятся с Официальный код (который мы надеемся выяснить из разборки), есть только два возможные причины сегментации неисправность.

Вы также можете подтвердить, как далеко в их распечатках дошли два потока до ошибки сегментации?

void thread::join()
{
    int res = 0;
#if defined(BOOST_HAS_WINTHREADS)
    res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
    assert(res == WAIT_OBJECT_0);
    res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
    assert(res);
#elif defined(BOOST_HAS_PTHREADS)
    res = pthread_join(m_thread, 0);
    assert(res == 0);
#elif defined(BOOST_HAS_MPTASKS)
    OSStatus lStatus = threads::mac::detail::safe_wait_on_queue(
        m_pJoinQueueID, NULL, NULL, NULL, kDurationForever);
    assert(lStatus == noErr);
#endif
    // This isn't a race condition since any race that could occur would
    // have us in undefined behavior territory any way.
    m_joinable = false;
}

Обычные причины возникновения таких проблем:

  • неинициализированные переменные
  • переменные, к которым обращаются оба потока, которые не были помечены volatile
  • встроенные вызовы и / или развернутые циклы (размер кадра стека которых является суммой стековых кадров всех экземпляров метода), вызываемые рекурсивно и переполняющие стек намного быстрее, чем не встроенные версии
2 голосов
/ 22 февраля 2009

Я нашел ошибку! Я связался с неверной версией библиотеки. Я использовал boost_thread-gcc-mt-s, но вместо этого он работает с boost_thread-gcc-mt:

g++ -O2 -o test-thread test-thread.cpp -lboost_thread-gcc-mt -lpthread

Я посмотрел документацию по бусту, но не смог найти никакой информации о различиях между этими версиями библиотеки. Существует также boost_thread-gcc-mt-d, который, как я полагаю, является отладочной версией, но связывание с этой версией всегда приводит к бинарным файлам, которые вызывают ошибку, даже при компиляции с -g. Но, по крайней мере, теперь я могу запускать темы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...