Question

J'ai du mal à obtenir boost:thread travailler. Il fonctionne très bien lors de la compilation sans optimisation:

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

Mais une version qui est compilé avec plantages optimisations

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

Quelqu'un sait-il ce qui pourrait être la raison?

Voici le code que je utilise:

#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 .: J'utilise boost 1,32 sur linux ubuntu.

Mise à jour:

Voici où il se bloque dans le débogueur (où la ligne 37 est celle qui thread_2.join(); dans mon code d'origine):

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

Voici mes deux fonctions réelles:

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

Merci pour toute aide!

Était-ce utile?

La solution 2

J'ai trouvé le bug! Je reliaient contre la mauvaise version de la bibliothèque. J'étais en utilisant boost_thread-gcc-mt-s, mais il fonctionne avec boost_thread-gcc-mt à la place:

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

J'ai regardé dans la documentation de coup de pouce, mais je ne pouvais pas trouver aucune information sur ce que les différences entre ces versions bibliothèque sont. Il y a aussi un boost_thread-gcc-mt-d, que je suppose est la version de débogage, mais contre liant que l'on aboutit toujours à des binaires qui Segfault, même lors de la compilation avec -g. Mais au moins je peux courir les fils maintenant.

Autres conseils

Pourriez-vous faire en sorte que les décharges de base sont actifs (ulimit -c unlimited), compilation avec des symboles (-O2 -g), exécuter et ouvrir la trace de la pile dans gdb? (gdb test-thread core, puis tapez backtrace à l'invite de gdb, quit de quitter)

  

UPDATE

     

Basé sur le backtrace, la   erreur de segmentation se produit dans   boost::thread::join. pouvez-vous   re-ouvrir le noyau et:

     
      
  • obtenir un démontage de la méthode de boost::thread::join:      
        
    • disassemble boost::thread::join
    •   
    • disassemble
    •   
  •   
  • obtenir une décharge des registres:      
        
    • info registers
    •   
  •   
     

La mise en œuvre de   boost::thread::join (stimuler 1,32   source officielle) est assez   tout droit vers l'avant, de sorte que si Ubuntu   binaires grossièrement diverger de la   code officiel (que nous l'espérons trouver à partir du démontage), il n'y a que deux   les causes possibles de la segmentation   défaut.

     

Pouvez-vous confirmer également dans quelle mesure leurs impressions les deux fils ont avant la 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;
}

causes habituelles pour ce genre de problèmes:

  • variables non initialisées
  • variables qui sont accessibles par les deux fils qui ne sont pas marqués volatile
  • appels inline et / ou des boucles (dont la taille non enroulé cadre pile est la somme de tous les cadres de pile de instances de méthode inlined) étant appelé récursive et débordants la pile beaucoup plus rapide que les versions non-inline
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top