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?
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:
return a std::string
instead of a char*
pointer.
allocate the char
data dynamically, and then make the caller free it when done using it.
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.