Frage

Ich habe Mühe, boost:thread zu arbeiten. Es läuft gut, wenn ohne Optimierung kompilieren:

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

Aber eine Version, die mit Optimierungen Abstürze

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

Wer weiß, was könnte der Grund sein?

Hier ist der Code verwende ich:

#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 .: Ich benutze Boost 1.32 auf Ubuntu Linux.

UPDATE:

Hier ist, wo es im Debugger stürzt (wo die Leitung 37 den mit thread_2.join(); in meinem ursprünglichen Code ist):

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

Hier sind meine eigentlichen zwei Funktionen:

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

Vielen Dank für jede Hilfe!

War es hilfreich?

Lösung 2

fand ich den Fehler! Ich hatte gegen die falsche Version der Bibliothek verknüpft. Ich hatte boost_thread-gcc-mt-s gewesen verwendet, aber es funktioniert mit boost_thread-gcc-mt statt:

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

schaute ich in die Boost-Dokumentation, aber ich konnte keine Informationen über nicht finden, was die Unterschiede zwischen diesen Bibliotheksversionen sind. Es gibt auch eine boost_thread-gcc-mt-d, die ich davon ausgehen, ist die Debug-Version, aber die Verknüpfung gegen das man immer zu Binärdateien, die segfault, selbst wenn sie mit -g kompilieren. Aber zumindest kann ich jetzt die Fäden laufen.

Andere Tipps

Könnten Sie sicher, dass Core-Dumps aktiv sind (ulimit -c unlimited), kompilieren mit Symbolen (-O2 -g) laufen, und öffnen Sie die Stack-Trace in gdb? (gdb test-thread core, geben Sie dann backtrace an der gdb Aufforderung quit zu beenden)

  

UPDATE

     

Auf der Grundlage der Backtrace, die   Segmentierungsfehler tritt in   boost::thread::join. Könntest du   wieder öffnen, die den Kern und:

     
      
  • eine Zerlegung des boost::thread::join Verfahren erhalten:      
        
    • disassemble boost::thread::join
    •   
    • disassemble
    •   
  •   
  • einen Dump des Registers erhalten:      
        
    • info registers
    •   
  •   
     

Die Umsetzung der   boost::thread::join (Boost 1,32   offizielle Quelle) ist ziemlich   geradlinig, so es sei denn, die Ubuntu   Binärdateien grob divergieren von der   offizieller Code (die wir hoffentlich von der Demontage herausfinden), gibt es nur zwei   Mögliche Ursachen für die Segmentierung   bemängeln.

     

Können Sie bestätigen auch, wie weit in ihren Ausdrucken die beiden Fäden vor dem Segmentierungsfehler haben?

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

Übliche Ursachen für diese Art von Problemen:

  • nicht initialisierten Variablen
  • Variablen, die von beiden Threads zugegriffen werden, die nicht markiert volatile wurden
  • inlined Anrufe und / oder abgerollt Schleifen (deren Stapelrahmengröße ist die Summe aller inlined Stack-Frames Methode Instanzen) rekursiv aufgerufen wird und die überquellenden Stapel viel schneller als die nicht-inlined Versionen
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top