문제

나는 얻는 데 어려움이있다 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;
}

추신 : 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

나는 버그를 찾았다! 나는 잘못된 버전의 라이브러리와 연결했다. 나는 사용하고 있었다 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, 내가 디버그 버전이라고 생각하지만, 그와 연결하면 컴파일 할 때에도 항상 segfault의 바이너리가 발생합니다. -g. 그러나 적어도 나는 지금 스레드를 실행할 수 있습니다.

다른 팁

코어 덤프가 활성화되어 있는지 확인할 수 있습니까 (ulimit -c unlimited), 기호 (-o2 -g)로 컴파일하고, 실행하고, 스택 추적을 GDB에서 엽니 다? (gdb test-thread core, 그런 다음 입력하십시오 backtrace ~에서 gdb 즉각적인, quit 종료합니다)

업데이트

백 트레이스를 기준으로, 분할 오류는 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