Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Temporary in a function call: UB? [duplicate]

Consider the following code, based on this answer:

#include <iostream>
#include <sstream>

class StringBuilder {
public:
    template <typename T> inline StringBuilder &operator<<(T const &t) {
        ss << t;
        return *this;
    }

    inline char const * c_str() {
        return ss.str().c_str();
    }

private:
    std::stringstream ss;
};

void foo(const char *x) {
    std::cout << x << std::endl;
}

int main() {
    foo((StringBuilder() << "testing " << 12 << 3 << 4).c_str());
    return 0;
}

Does calling foo() with the temporary StringBuilder's return value cause UB in any way?

The reason I'm asking is that the example above works great, but in real life I'm using a library that, amongst other things, contains logging facilities, and using this library I'll get incorrect output (the logging function takes my char* correctly but overwrites it internally, which caused me to believe that the memory is no longer valid).

like image 718
rainer Avatar asked Mar 11 '23 05:03

rainer


1 Answers

Yes, but not because of what you perhaps think.

The temporary StringBuilder in the function call is not destroyed until after foo returns, so that's fine.

However, the c_str() method returns the result of calling .str().c_str(), and the temporary string returned by this str() is destroyed as StringBuilder::c_str() returns, which means that the pointer returned is invalid outside. Using this pointer causes UB.

like image 128
Sebastian Redl Avatar answered Mar 19 '23 16:03

Sebastian Redl