c++lifetimestringstream

Out of scope issue?


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?


Solution

  • 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()
    }