Pergunta

Eu tenho problemas para obter boost:thread ao trabalho. Ele funciona muito bem quando compilar sem otimização:

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

Mas uma versão que é compilado com otimizações acidentes

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

Alguém sabe o que pode ser a razão?

Aqui está o código que estou usando:

#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 .: Eu estou usando boost 1,32 no Ubuntu Linux.

UPDATE:

Aqui é onde ele trava no depurador (onde a linha 37 é o único com thread_2.join(); no meu código original):

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

Aqui estão as minhas reais duas funções:

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;
}

Obrigado por qualquer ajuda!

Foi útil?

Solução 2

Eu encontrei o bug! Eu tinha ligado contra a versão errada da biblioteca. Eu tinha sido usando boost_thread-gcc-mt-s, mas funciona com boost_thread-gcc-mt vez:

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

Eu olhei para a documentação impulso, mas eu não poderia encontrar qualquer informação sobre o que as diferenças entre essas versões da biblioteca estão. Há também um boost_thread-gcc-mt-d, que eu suponho que é a versão de depuração, mas que liga contra o que sempre resulta em binários que segfault, mesmo quando compilando com -g. Mas pelo menos eu posso correr os fios agora.

Outras dicas

Você poderia ter certeza de que descarregar um core são ativos (ulimit -c unlimited), compilação com símbolos (-O2 -g), Executar e abrir o rastreamento de pilha no gdb? (gdb test-thread core, em seguida, digite backtrace no gdb alerta, quit parar)

Atualizar

Com base no registo de chamadas, o falha de segmentação ocorre em boost::thread::join. Você poderia re-abrir o núcleo e:

  • obter uma desmontagem do método boost::thread::join:
    • disassemble boost::thread::join
    • disassemble
  • obter um despejo dos registros:
    • info registers

A implementação de boost::thread::join (boost 1,32 fonte oficial) é bastante straight-forward, então a menos que o Ubuntu binários grosseiramente divergir do código oficial (que nós esperamos descobrir a partir do desmontagem), existem apenas dois possíveis causas para a segmentação falha.

Pode também confirmar o quão longe em suas impressões os dois tópicos tem antes da falha de segmentação?

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;
}

causas usuais para esses tipos de problemas:

  • variáveis ??não inicializadas
  • variáveis ??que são acessados ??por ambos os tópicos que não foram marcados volatile
  • chamadas e / ou loops desenroladas (cuja pilha tamanho do quadro é a soma dos quadros de pilha todas as instâncias do método sequenciais) que está sendo chamado de forma recursiva e transbordando a pilha muito mais rápido do que as versões não-inline inline
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top