2017-12-05 2 views
-3

콘솔에 메시지를 인쇄하는 간단한 threadsafe 로거를 사용하려고했습니다.다중 스레드 응용 프로그램에서 문자열 스트림을 사용하는 분할 오류 (코어 덤프)

// Test function for check logger. It is work 
void test(double& diff) 
{ 
    std::vector<double> result; 
    for(int counter = 0; counter < 100000; ++counter) 
    { 
    result.push_back(clock()); 

    std::string text = "counter = "; 
    text.append(std::to_string(counter)); 
    LOG_MESSAGE(text); //<-- Correct log.. 
    } 
    diff = clock() - result.front(); 

} 

int main(int argc, char** argv) 
{ 
    double time2; 
    double time1; 
    std::vector<double> timerResult; 
    std::vector<std::thread> threadVector; 

    time1 = clock(); 
    for(int i = 0; i < 5; ++i) //<-- Create 5 thread of test function 
    { 
    timerResult.push_back(0); 
    threadVector.push_back(std::thread(test, std::ref(timerResult[i]))); 
    } 
    for(std::thread& t : threadVector) 
    t.join(); 
    time2 = clock(); //<-- Threads is finished 

    double res = 0; 
    for(double tRes : timerResult) 
    res += tRes; 
    res = res/static_cast<double>(CLOCKS_PER_SEC); 

    std::string message; //<-- Generate final message 
    message.append("Timer: ") 
     .append(std::to_string((time2 - time1)/(double)CLOCKS_PER_SEC)) 
     .append(" - thread timer: ") 
     .append(std::to_string(res)); 

    LOG_MESSAGE(message); //<-- Crash inside!!  

    return 0; 
} 

로거는 스레드에서 작동합니다. 그러나 나는 (구조 로그 메시지의 기능에) 표준 : : ostringstream의 소멸자에서 SIGSEGV 신호를 호출 main() 함수에 로그인하려고하면

static Logger::Core logger; //<--Global Logger variable 

#define LOG_MESSAGE(TEXT) logger.addNoteInLog(TEXT) //<-- Define for log message 

void Core::addNoteInLog(const Message &message) //<-- threadsafe log function 
{ 
    std::string text; 
    message.generateString(text); //<-- [Crash here] generate log message 
    g_lock.lock(); 
    std::cout << text; 
    g_lock.unlock(); 
} 

void Message::generateString(std::string& text) const 
{ 
    text.clear(); 
    tm *ltm = localtime(&mDate); 

    std::ostringstream data; //<-- [Crash here] function is finished, but cannot destruct object. 
    data << 1900 + ltm->tm_year << "/" 
     << 1 + ltm->tm_mon << "/" 
     << ltm->tm_mday << "\t"; 
    data << "[INF] - "; 
    data << std::this_thread::get_id() << " - " 
     << mMessage << "\n"; 

    text = data.str(); 
} 

내가 스레드 로거 작품입니다 이유를 이해 해달라고하지만, 메인에() 함수가 중단되었습니다. 제외 방법을 사용하여, 나는 오류가 발생한 경우 발견 :

  • 나는 5 (이상) 스레드를 사용할 때
  • 테스트 기능이 비어 있지
  • 때 generateString 사용 이제 stringstream 또는 ostringstream 또는 문자열 .append() (마지막 경우에 같은 장소에서 std :: string 소멸자에서 응용 프로그램이 충돌 함)

QtCreater에서 어떤 say 디버거가 사용됩니까? 우분투 OS에서

빌드, 버전의 gcc 5.4.0 컴파일 플래그 : -std=c++17 -pthread -Wall

This 오류 내 자식 저장소입니다.

+0

은 참고하시기 바랍니다 문서는 localtime'는 스레드 안전하지 않을 수'있습니다. 자물쇠 안에'generateString' 호출을 옮기면 어떻게 될까요? –

+0

세그먼트 오류가 파란색에서 나오지 않습니다. 디버거에서 스택 추적을 검사 했습니까? 정확히 어디에서 코드가 왔습니까? – user0042

+1

벡터를 확인하십시오. vector가 자라면 저장 공간을 완전히 재 할당 할 것이므로 스레드가 쓰레기를 가리킬 수 있습니다. 예비를 사용하여 벡터 크기를 조정하면 도움이 될 수 있습니다. –

답변

0

문제가 해결되었습니다. push_back을 5 번 호출 한 후 메모리 재 할당이 timerResult에 있었고 ref(timerResult[i])에 의한 참조 전달이 올바르지 않아서 주석에서 말한 것처럼 threadVector.push_back(std::thread(test, std::ref(timerResult[i]))); 줄이 올바르지 않습니다.

올바른 코드 :

int main(int argc, char** argv) 
    { 
     double time2; 
     double time1; 
     std::vector<double> timerResult (5); //<-- Create filling of vector 
     std::vector<std::thread> threadVector; 

     time1 = clock(); 
     for(int i = 0; i < 5; ++i) 
     { 
     //timerResult.push_back(0); //<-- incorrect filling of vector 
     threadVector.push_back(std::thread(test, std::ref(timerResult[i]))); 
     } 
     for(std::thread& t : threadVector) 
     t.join(); 
     time2 = clock(); 
     ... 
    }