简体   繁体   中英

The substring shouldnotexist in an operand causes std::string concatenation by + operator to return an empty string

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.

eg /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?

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 eg concatenation, it is invalidated immediately afterwards, as the temporary object goes out of scope:

  1. A temporary string instance for the concatenated string is created: std::string _temporary = a + std::string("shouldnotexist");
  2. The c_str method is called on it, storing the result: path = _temporary.c_str()
  3. The temporary instance goes out of scope, deleting the string, invalidating the pointer stored in path .
  4. You use the now-invalid stored pointer for 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM