c++exceptiongarbage

Returning const char* from funciton


I have this function, where I'm trying to return a const char*, but when I try to output the returned value, I get garbage value;

virtual const char* what() const noexcept 
{
    std::stringstream s;
    if(m_id > -1)
        s << m_message << " with id " << m_id << " does not exist";
    else
        s << m_message << " with name " << m_name << " does not exist";
    
    //until now it works fine

    std::string tmp = s.str();
    const char* temp = tmp.c_str();

    return temp; //after I execute this command, the value is deleted.
}

when I try to print:

catch (std::exception& e) 
{   
    std::cout << e.what() << std::endl;
}

I get this (different every time..) :

▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌╢Pⁿש▌'

What am I doing wrong?


Solution

  • You are returning a pointer to the internal char data of a local std::string object that is destroyed when the function exits, thus the returned pointer is left dangling, pointing at invalid memory. Trying to access the data afterwards is undefined behavior.

    Normally, you would have two choices to fix that:

    However, in this case, you are overriding the std::exception::what() method, so neither of those options are viable. What you will have to do instead is store your char data in a std::string member of your derived class, and then you can return a char* pointer to its data, eg:

    private:
        std::string m_what;
    
    myException::myException(...) 
    {
        ...
        std::stringstream s;
        if (m_id > -1)
            s << m_message << " with id " << m_id << " does not exist";
        else
            s << m_message << " with name " << m_name << " does not exist";
    
        m_what = s.str();
    }
    
    virtual const char* what() const noexcept 
    {
        return m_what.c_str();
    }
    

    If you derive your exception class from std::runtime_error instead of std::exception directly, this is already handled for you. std::runtime_error takes a string in its constructor, and overrides what() to return that string's data.