boost :: thread: Segfault lors de l'exécution version optimisée
-
05-09-2019 - |
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!
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