2016-09-12 14 views
0

This answerprivate static ostringstreamと宣言しています。このスレッドは安全ですか? 2つのスレッドが同時に例外をスロー(キャッチしてログに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除算誤差は、数学的誤差に関連する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)); 
    } 

}; 
関連する問題