This answer declares a private static ostringstream
. Is this thread safe? If two threads throw (and catch, and log what()
) the exception at the same time, does this work reliably? If I declare the ostringstream
locally, like:
virtual const char* what() const throw()
{
std::ostringstream cnvt.str( "" );
cnvt << runtime_error::what() << ": " << getNumerator()
<< " / " << getDenominator();
return cnvt.str().c_str();
}
Is there a drawback (memory leak, or illegal pointer)? Or is this the thread-safe way?
No. it's not safe at all (and pretty inefficient to my taste, can be done with std::string
alone).
in order to make it safe, declare the ostringstream
as thread_local
static thread_local ostringstream cnvt;
also, you should make the cnvt
output the string to some member string in order to not return a dangling pointer.
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;
};
also, if the exception is "divide by zero" don't you think it's a bit silly storing the denominator? it's always a zero! otherwise you wouldn't throw "division by zero" error!
and finally 0-division error is more appropriate to be derived from std::domain_error
which related to mathematical errors.