부스트 :: 스레드 : segfault 최적화 버전을 실행할 때
-
05-09-2019 - |
문제
나는 얻는 데 어려움이있다 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
- 상실 된 통화 및/또는 롤링 루프 (스택 프레임 크기는 모든 상감 된 메소드 인스턴스 스택 프레임의 합계)를 재귀 적으로 호출하고 스택을 무감각 한 버전보다 훨씬 빨리 넘치게합니다.