3

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

PS:我在 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;
}

谢谢你的帮助!

4

2 回答 2

3

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

更新

根据回溯,分段错误发生在 boost::thread::join. 您能否重新打开核心并:

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

(boost 1.32 官方源代码)的实现 boost::thread::join非常简单,因此除非 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
  • 内联调用和/或展开循环(其堆栈帧大小是所有内联方法实例的堆栈帧的总和)被递归调用并且比非内联版本更快地溢出堆栈
于 2009-02-21T01:47:44.983 回答
3

我发现了错误!我链接了错误版本的库。我一直在使用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. 但至少我现在可以运行线程了。

于 2009-02-21T21:17:43.643 回答