Этот ответ объявляет private static ostringstream
, Эта тема безопасна? Если два потока кинь (и лови, и лог what()
) исключение в то же время, это работает надежно? Если я объявлю ostringstream
локально, как:
virtual const char* what() const throw()
{
std::ostringstream cnvt.str( "" );
cnvt << runtime_error::what() << ": " << getNumerator()
<< " / " << getDenominator();
return cnvt.str().c_str();
}
Есть ли недостаток (утечка памяти или недопустимый указатель)? Или это потокобезопасный способ?
Нет, это совсем не безопасно (и довольно неэффективно, на мой вкус, может быть сделано с std::string
в одиночестве).
чтобы сделать его безопасным, объявить ostringstream
как thread_local
static thread_local ostringstream cnvt;
Кроме того, вы должны сделать 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
которые связаны с математическими ошибками.
what()
это неправильное место для построения строки ИМХО (хотя существуют разные взгляды на это).
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));
}
};