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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With