9

Do I need to take care of memory allocation, scope and deletion of C++ strings allocated by a literal?

For example:

#include <string>

const char* func1() {
    const char* s = "this is a literal string";
    return s;
}

string func2() {
    std::string s = "this is a literal string";
    return s;
}

const char* func3() {
    std::string s = "this is a literal string";
    return s.c_str();
}

void func() {
    const char*  s1 = func1();
    std::string s2 = func2();
    const char*  s3 = func3();

    delete s1; //?
    delete s3; //?
}
  • func2: I don't need to delete s2.
  • func3: Do I need to delete s3?

Is func1 correct? Is character memory content still available after it leaving func1's scope? If yes, should I delete it when I do not need it anymore?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
rnd_nr_gen
  • 2,203
  • 3
  • 36
  • 55

4 Answers4

18
  • func1() returns a pointer to a string literal. You must not delete string literals.
  • func2() (presumably, you omitted the std:: prefix) returns a std::string. It takes care of itself.
  • func3() returns a pointer to a string that's managed by a std::string object that's destroyed when the function exits. You must not touch that pointer after the function returns.
  • You would have to take care of the memory returned by this function:

    const char* func4() {
       char* s = new char[100];
       // fill char array with a string
       return s;
    }
    

However, manual resource management is tricky. For starters, if a function returns a naked pointer, you don't know whether it points to one objects (char) or an array thereof and whether you need to delete it. You should avoid all that and just stick to std::string.

sbi
  • 219,715
  • 46
  • 258
  • 445
3

You have a different problem with s3, namely that the function func3() returns a pointer into an object that goes out of scope when the function returns. Don't.

To clarify: Your local string object within func3() will cease to exist on return of the function, so no need to delete. However, you still have a pointer to its internal buffer, which you return. You can't use that.

Very good and detailed past answer here, lest more confusion ensues: Is it more efficient to return a const reference

Community
  • 1
  • 1
Alexander Rautenberg
  • 2,205
  • 2
  • 22
  • 20
  • @Alexander Rautenberg - Better would be to ask him to use a reference for s3, rather than a pointer. And it is correct anyways. – DumbCoder Oct 07 '10 at 12:55
  • The problem remains the same for func3() or s3, if you use a pointer or a reference. There is nothing correct about the way func3() is coded. – Alexander Rautenberg Oct 07 '10 at 15:23
  • @Alexander Rautenberg - Not in a reference, for strings, if you check properly. Returning an object but binding it to a const object increases its lifetime till the program exits. If he returns a string instead of a char pointer he is fine. – DumbCoder Oct 07 '10 at 15:56
  • @DumbCoder If he returns a std::string, he's fine, agreed. But I think the original question was about using delete with pointers in different situations, and this is where func3() cannot be made to fit in. – Alexander Rautenberg Oct 07 '10 at 17:03
1

I snip the relevant code to each function and treatment of its return value, and comment below:

const char* func1() {
   const char* s = "this is a literal string";
   return s;
}
const char*  s1 = func1();
delete s1; //?

You can't delete s1, as the string it points to does not live on the heap.

string func2() {
   string s = "this is a literal string";
   return s;
}
string s2 = func2();

This is fine. func2's s goes out of scope and cleans up. s2 will duplicate the string from s, and also clean itself up at the end of func.

const char* func3() {
   string s = "this is a literal string";
   return s.c_str();
}
const char*  s3 = func3();
delete s3; //?

func3 returns a pointer to a string that has been freed. You will get a double free exception upon execution of delete s3.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
1

In func3 your string local is created by the compiler calling the implicit constructor string(const char*) initializing its internal buffer with a copy of the string literal. You then return a pointer to the internal buffer of the string which promptly goes out of scope and gets freed as soon as the function returns.

joshperry
  • 41,167
  • 16
  • 88
  • 103
  • To be more precise, the allocated string (temporary) gets destroyed not when the function returns per se, but when the expression which called func3() ends. This is not a subtlety. It is a feature guaranteed by the C++ standard. – jose.angel.jimenez Dec 21 '21 at 14:17
  • @jose.angel.jimenez Very interesting. Does this guarantee have a name, or do you know a good search term to learn more about its purpose? – joshperry Feb 18 '22 at 03:39
  • You can check it in the latest draft of the C++11 specification, section "12.2 Temporary objects" paragraph 3: "[...] Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception [...]" http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3242.pdf – jose.angel.jimenez Feb 21 '22 at 10:24