Domanda

Non ho difficoltà a raggiungere boost:thread al lavoro. Funziona benissimo quando si compila senza ottimizzazione:

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

Ma una versione che è compilato con ottimizzazioni crash

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

Qualcuno sa che cosa potrebbe essere il motivo?

Ecco il codice che sto 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 .: Sto usando spinta 1.32 su Ubuntu Linux.

UPDATE:

Qui è dove si blocca nel debugger (dove la linea 37 è quella con thread_2.join(); nel mio codice originale):

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

Ecco le mie attuali due funzioni:

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

Grazie per qualsiasi aiuto!

È stato utile?

Soluzione 2

Ho trovato il bug! Avevo legato con la versione sbagliata della biblioteca. Ero stato con boost_thread-gcc-mt-s, ma funziona con boost_thread-gcc-mt invece:

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

Ho guardato nella documentazione di spinta, ma non sono riuscito a trovare alcuna informazione su ciò che le differenze tra le versioni della libreria sono. C'è anche un boost_thread-gcc-mt-d, che presumo sia la versione di debug, ma collegando contro che uno si traduce sempre in file binari che segfault, anche quando si compila con -g. Ma almeno posso correre i fili ora.

Altri suggerimenti

Potresti fare in modo che i core dump sono attivi (ulimit -c unlimited), compilare con i simboli (-O2 -g), correre, e aprire la traccia dello stack in gdb? (gdb test-thread core, quindi digitare al prompt backtrace gdb, quit per uscire)

  

Aggiorna

     

In base alla backtrace, il   segmentation fault si verifica in   boost::thread::join. Potresti   riaprire il nucleo e:

     
      
  • ottenere uno smontaggio del metodo boost::thread::join:      
        
    • disassemble boost::thread::join
    •   
    • disassemble
    •   
  •   
  • ottenere un dump dei registri:      
        
    • info registers
    •   
  •   
     

L'attuazione di   boost::thread::join (incrementare 1.32   fonte ufficiale) è abbastanza   straight-forward, quindi a meno che l'Ubuntu   binari grossolanamente divergono dalla   codice ufficiale (di cui parleremo si spera scopriremo dal smontaggio), ci sono solo due   possibili cause per la segmentazione   colpa loro.

     

Puoi confermare anche quanto lontano nelle loro stampe i due fili ottenuto prima del segmentation fault?

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

cause usuali per questo tipo di problemi:

  • variabili non inizializzate
  • variabili che sono accessibili da entrambi i fili non contrassegnati volatile
  • le chiamate inline e / o loop srotolati (il cui stack di grandezza è la somma di tutti gli stack frame metodo istanze inline) di essere chiamato in modo ricorsivo e traboccanti lo stack molto più veloce rispetto alle versioni non-inline
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top