2016-09-12 4 views
0

This answerprivate static ostringstream을 선언합니다. 이 스레드는 안전한가요? 두 스레드가 동시에 예외를 throw (catch 및 log what())하면이 작업이 안정적으로 작동합니까? 내가 좋아하는, 로컬 ostringstream를 선언하는 경우 :C++ 예외의 문자열 작성

virtual const char* what() const throw() 
{ 
    std::ostringstream cnvt.str(""); 
    cnvt << runtime_error::what() << ": " << getNumerator() 
     << "/" << getDenominator(); 
    return cnvt.str().c_str(); 
} 

는 단점 (메모리 누수, 또는 불법 포인터)가 있습니까? 아니면 스레드로부터 안전한 방법입니까?

+3

코드에서 범위를 벗어나는 문자열에 대한 포인터를 반환하면 정의되지 않은 동작이 발생합니다. –

답변

4

아니요. 내 취향에 전혀 안전하지 않습니다 (std::string 만 사용 가능). 이 안전하게하기 위해
, 당신이 허상 포인터를 반환하지하기 위해 cnvt 출력 일부 회원 문자열로 문자열을해야한다, 또한 ostringstream

thread_local

static thread_local ostringstream cnvt;

을 선언합니다.

class DivideByZeroException: public runtime_error { 
public: 

    DivideByZeroException(int x, int y) 
    : runtime_error("division by zero"), numerator(x), denominator(y) 
    {} 

    virtual const char* what() const throw() 
    { 
    cnvt.str(""); 

    cnvt << runtime_error::what() << ": " << getNumerator() 
     << "/" << getDenominator(); 

    error = cnvt.str(); 
    return error.c_str(); 
    } 

    /*...*/ 

    private: 
    std::string error; 
    int numerator; 
    int denominator; 

    static thread_local ostringstream cnvt; 
}; 

예외가 "제로로 나누기"인 경우 분모를 저장하는 것이 바보 같지 않습니까? 항상 0입니다! 그렇지 않으면 "0으로 나누기"오류가 발생하지 않습니다.

마지막으로 0 분주 오류는 수학적 오류와 관련된 std::domain_error에서 파생 된 것이 더 적절합니다.

1

what()은 IMHO 문자열을 작성하는 데 잘못된 위치입니다 (다른보기가 있음에도 불구하고).

std::runtime_error에는 이미 문자열이 포함되어 있으므로 사용하겠습니다.

#include <stdexcept> 
#include <string> 

struct DivideByZero : std::runtime_error 
{ 

    DivideByZero(int x, int y) 
    : std::runtime_error(make_message(x,y)) 
    {} 

private: 
    static std::string make_message(int x, int y) 
    { 
     return std::string("division by zero: " + std::to_string(x) + '/' + std::to_string(y)); 
    } 

};