1

这个答案声明了一个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();
}

是否有缺点(内存泄漏或非法指针)?或者这是线程安全的方式?

4

2 回答 2

4

不,这根本不安全(而且对我来说效率很低,可以单独完成std::string)。
为了安全起见,声明ostringstreamthread_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;
};

另外,如果例外是“除以零”,您不认为存储分母有点愚蠢吗?它总是一个零!否则你不会抛出“除以零”错误!

std::domain_error最后,与数学误差有关的0除法误差更适合推导出来。

于 2016-09-12T11:32:05.593 回答
1

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));
    }

};
于 2016-09-12T11:50:45.267 回答