I am using a framework that has been working for years on CentOS 7. We are migrating it to RHEL 8 and a few of the unit tests are failing. One in particular involves junk getting returned from what() on a std::runtime_error. I created a very simple example that duplicates the problem. It works on CentOS7 but not RHEL 8. Here is the code:
#include <sstream>
#include <iostream>
const char * getString() {
std::ostringstream oss;
oss << "some stuff to return" << std::endl;
std::cout << "value to return: " << oss.str().c_str() << std::endl;
return oss.str().c_str();
}
int
main(int argc, char ** argv) {
std::string value = getString();
std::cout << "value returned: " << value << std::endl;
return 0;
}
The output for CentOS7 is:
[user@localhost ~]$ ./a.out
value to return: some stuff to return
value returned: some stuff to return
while the output on RHEL8 is:
[user@localhost badoverload]$ ./a.out
value to return: some stuff to return
value returned: `
Is the value going out of scope and unavailable but the memory just happens to be untouched in CentOS 7? Or is something else going on?
getString()
returns a dangling pointer here:
return oss.str().c_str();
The std::string
returned by str()
is temporary and gets destroyed when it goes out of scope at the end of the whole expression.
So, when you do...
std::string value = getString();
... that reads from the dangling pointer, the whole program has undefined behavior.
Just return a std::string
instead of a const char*
:
std::string getString() {
//...
return oss.str(); // not c_str()
}