سؤال

لدي مشكلة في الحصول عليها boost:thread للعمل. يعمل بشكل جيد عند تجميع دون تحسين:

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

لكن النسخة التي تم تجميعها مع تعطل التحسينات

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

لا أحد يعرف ما قد يكون السبب؟

هنا هو الرمز الذي أستخدمه:

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

ملاحظة: أنا أستخدم دفعة 1.32 على Ubuntu Linux.

تحديث:

هنا هو المكان الذي تعطل في المصحح (حيث السطر 37 هو واحد مع thread_2.join(); في التعليمات البرمجية الأصلية):

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

فيما يلي وظيفتي الفعلية:

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

شكرا على اي مساعدة!

هل كانت مفيدة؟

المحلول 2

لقد وجدت الخلل! كنت مرتبطا بالنسخة الخاطئة من المكتبة. كنت تستخدم boost_thread-gcc-mt-s, ، لكنها تعمل مع boost_thread-gcc-mt في حين أن:

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

نظرت إلى وثائق دفعة، لكنني لم أستطع العثور على أي معلومات حول ما هي الاختلافات بين إصدارات المكتبة تلك. هنالك أيضا boost_thread-gcc-mt-d, ، الذي أفترض أنه إصدار تصحيح الأخطاء، ولكن يربط ضد ذلك ينتج عنه دائما ثنائيات أن Segfault، حتى عند تجميعها -g. وبعد ولكن على الأقل يمكنني تشغيل الخيوط الآن.

نصائح أخرى

هل يمكن أن تتأكد من أن مقالب النواة نشطة (ulimit -c unlimited)، تجميع الرموز (-O2 -G)، تشغيل، وفتح أثر المكدس في GDB؟ فيgdb test-thread core, ، ثم اكتب backtrace في ال gdb مستعجل، quit ليستقيل)

تحديث

بناء على Backtrace، يحدث خطأ تجزئة في boost::thread::join. وبعد هل يمكن أن تعيد فتح القلب و:

  • الحصول على تفكيك boost::thread::join طريقة:
    • disassemble boost::thread::join
    • disassemble
  • الحصول على تفريغ السجلات:
    • info registers

تنفيذ boost::thread::join (دفعة 1.32 مصدر رسمي) إلى الأمام بشكل مستقيم، لذلك ما لم تتباعد ثنائيات أوبونتو بشكل صارخ من القانون الرسمي (الذي سنكتشفه من التفكيك)، لا يوجد سوى سببان محتملان لخطأ التجزئة.

هل يمكنك أيضا تأكيد مدى المسافة في نشر الرسوم البيانية التي حصلت عليها المواضيع اثنين قبل خطأ التجزئة؟

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

الأسباب المعتادة لهذه الأنواع من المشاكل:

  • متغيرات غير مهيأة
  • المتغيرات التي يتم الوصول إليها من قبل كل من المواضيع التي لم يتم وضع علامة volatile
  • المكالمات المتنقلة و / أو الحلقات غير المنضكة (حجم إطار المكدس الخاص بها مجموع إطارات المكدسات الخاصة به لجميع مثيلات الأسلوب المطلقة) تطلق بشكل متكرر وتفيض الكومة أسرع بكثير من الإصدارات غير المملغة
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top