Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

string

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;
}
like image 819
user3338893 Avatar asked Dec 23 '14 20:12

user3338893


People also ask

How does c_str () work?

The c_str() method converts a string to an array of characters with a null character at the end. The function takes in no parameters and returns a pointer to this character array (also called a c-string).

What does string c_str return?

The c_str method of std::string returns a raw pointer to the memory buffer owned by the std::string .

Is string c_str null-terminated?

c_str returns a "C string". And C strings are always terminated by a null character. This is C standard.

What is the type of c_str ()?

c_str() converts a C++ string into a C-style string which is essentially a null terminated array of bytes.


2 Answers

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.

like image 158
Pradhan Avatar answered Oct 01 '22 03:10

Pradhan


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.

like image 36
kec Avatar answered Oct 01 '22 02:10

kec