user3338893
user3338893

Reputation: 977

Why does calling c_str() on a function that returns a string not work?

I have a function that is returning a string. However, when I call it and do c_str() on it to convert it into a const char*, it only works when I store it into another string first. If I directly call c_str() off of the function, it stores garbage value in the const char*.

Why is this happening? Feel like I'm missing something very fundamental here...

string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value

static string SomeFunction()
{
    string str;
    // does some string stuff
    return str;
}

Upvotes: 23

Views: 15307

Answers (4)

Lin GU
Lin GU

Reputation: 89

  1. The "string str" in method SomeFunction() is a local variable in SomeFunction(), and only survives inside the scope of SomeFunction();

  2. Since the return type of the method SomeFunction() is string, not a reference of string, after "return str;", SomeFunction() will return a copy of the value of str, which will be stored as a temporary value in some place of memory, after the call of SomeFunction(), the temporary value will be destroyed immediately;

  3. "string str = SomeFunction();" will store the returned temporary value of SomeFunction() to string str, actually is a copy of that value and stored to str, a new memory block is allocated, and the lifetime of str is bigger than the returned temporary value of SomeFunction(), after the ";" the call of SomeFunction() is finished, and the returned temporary value is destroyed immediately, the memory is recycled by system, but the copy of this value is still stored in str. That is why "const char* strConverted = str.c_str();" can get the right value, actually c_str() returned a pointer of the initial element of str (the first element memory address of str pointed string value), not the returned temporary value of SomeFunction();

  4. "const char* charArray= SomeFunction().c_str();" is different, "SomeFunction().c_str()" will return a pointer of the initial element of the returned temporary value (the first element memory address of returned temporary string value), but after the call of SomeFunction(), the returned temporary value is destroyed, and that memory address is reused by the system, charArray can get the value of that memory address, but not the value you expected;

Upvotes: 1

kec
kec

Reputation: 2149

The value object returned by a function is a temporary. The results of c_str() are valid only through the lifetime of the temporary. The lifetime of the temporary in most cases is to the end of the full expression, which is often the semicolon.

const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.

The workaround is to make sure that you use the result of c_str() before the end of the full expression.

#include <cstring>

char *strdup(const char *src_str) noexcept {
    char *new_str = new char[std::strlen(src_str) + 1];
    std::strcpy(new_str, src_str);
    return new_str;
}

const char *p = strdup(SomeFunction.c_str());

Note that strdup is a POSIX function, so if you are a platform that supports POSIX, it's already there.

Upvotes: 4

Pradhan
Pradhan

Reputation: 16737

SomeFunction().c_str() gives you a pointer to a temporary(the automatic variable str in the body of SomeFunction). Unlike with references, the lifetime of temporaries isn't extended in this case and you end up with charArray being a dangling pointer explaining the garbage value you see later on when you try to use charArray.

On the other hand, when you do

string str_copy = SomeFunction();

str_copy is a copy of the return value of SomeFunction(). Calling c_str() on it now gives you a pointer to valid data.

Upvotes: 31

Bruce
Bruce

Reputation: 2310

Use strcpy to copy the string to a locally defined array and your code will work fine.

Upvotes: -5

Related Questions