Reputation: 1651
Background - I was writing a benchmark to measure the cost of stat
on a missing file and appended the string "shouldNotExist" to the end of a filepath to do so.
e.g. /foo
should become /fooshouldNotExist
However, the code was just trying to stat an empty string "".
After digging a little deeper, I noticed that when concatenating two std::string
types using the +
operator, the result is an empty string if the result is not stored in an std::string
immediately. For example, in the code below, I wrap it in parenthesis and convert to c_str().
I'm using g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
.
#include <stdio.h>
#include <string>
int main() {
const char *path, *x, *y;
std::string a = "abcd";
std::string result;
path = (a + std::string("shouldnotexist")).c_str();
printf("path is [%s]\n", path); // path is []
x = std::string("shouldnotexist").c_str();
printf("x is [%s]\n", x); // path is [shouldnotexist]
y = (std::string("hello") + x).c_str();
printf("y is [%s]\n", y); // path is []
path = (a + std::string("fooo")).c_str();
printf("path is [%s]\n", path); // path is [abcdfoo]
path = (a + std::string("foooshouldnotexist")).c_str();
printf("path is [%s]\n", path); //path is []
path = (std::string("fooshouldnotexist") + a).c_str();
printf("path is [%s]\n", path); // path is []
result = std::string("fooshouldnotexist") + a;
// Storing in an intermediate std::string appears to work
// path is [fooshouldnotexistabcd], length is 21
printf("path is [%s], length is %lu\n", result.c_str(), result.length());
return 0;
}
Are you observing a similar result? If so, why does this happen and is it documented anywhere?
Upvotes: 0
Views: 42
Reputation: 8071
c_str
gives you a pointer to the contents of a string instance to use in plain-C functions (like printf). However, when you apply it on a temporary string instance created by e.g. concatenation, it is invalidated immediately afterwards, as the temporary object goes out of scope:
std::string _temporary = a + std::string("shouldnotexist");
c_str
method is called on it, storing the result: path = _temporary.c_str()
path
.printf
.As you write, by storing the temporary instance in a variable, the problem goes away, because now the instance does not go out of scope prior to the printf, keeping the pointer valid.
Upvotes: 2