c++multithreadingexceptionstring-building

String building in C++ exception’s what()


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?


Solution

  • 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.