Строение строк в C++ исключение what()

Этот ответ объявляет 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();
}

Есть ли недостаток (утечка памяти или недопустимый указатель)? Или это потокобезопасный способ?

2 ответа

Решение

Нет, это совсем не безопасно (и довольно неэффективно, на мой вкус, может быть сделано с 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));
    }

};
Другие вопросы по тегам