boost :: thread:运行优化版本时的Segfault

时间:2009-02-21 01:24:15

标签: multithreading segmentation-fault boost-thread

我无法让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;
}

P.S。:我在ubuntu linux上使用boost 1.32。

更新

以下是调试器崩溃的地方(第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 个答案:

答案 0 :(得分:3)

您能否确保核心转储处于活动状态(ulimit -c unlimited),使用符号(-O2 -g)进行编译,运行并在gdb中打开堆栈跟踪? (gdb test-thread core,然后在backtrace提示符下输入gdbquit退出)

  

<强>更新

     

基于回溯,   分段故障发生在   boost::thread::join。您可以...吗   重新打开核心,并且:

     
      
  • 获取boost::thread::join方法的反汇编:      
        
    • disassemble boost::thread::join
    •   
    • disassemble
    •   
  •   
  • 获取寄存器的转储:      
        
    • info registers
    •   
  •   
     

执行   boost::thread::join(提升1.32   官方来源)很漂亮   直截了当,所以除非是Ubuntu   二进制文件严重偏离了   官方代码(我们希望从反汇编中找到),只有两个   分割的可能原因   故障。

     

您是否还可以确定在分段错误之前两条线程的打印输出有多远?

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
  • 的线程访问的变量
  • 内联调用和/或展开循环(其堆栈帧大小是所有内联方法实例的堆栈帧的总和)被递归调用并且比非内联版本更快地溢出堆栈

答案 1 :(得分:2)

我发现了这个错误!我已经链接到错误的库版本。我一直在使用boost_thread-gcc-mt-s,但它适用于boost_thread-gcc-mt

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

我查看了boost文档,但是我找不到有关这些库版本之间差异的信息。还有一个boost_thread-gcc-mt-d,我假设它是调试版本,但链接到那个版本总是会产生段错误,即使用-g进行编译也是如此。但至少我现在可以运行线程了。