user3370198
user3370198

Reputation: 71

Getting error with const char

I am trying to implement the functions below, but the output for foo() is a bunch of nonsense. I tried to run the debugger and didn't see any problems inside the append function. But the total variable in foo() isn't properly assigned the value "abcdef". Any ideas why?

int main()
{
    cout<<"foo is"<<endl;
    foo();
    return 0;
}

const char* append(const char* s1, const char* s2) {
    string s(s1);
    s += s2;
    return s.c_str();
}

void foo() {
    const char* total = append("abc", "def");
    cout<<total;
}

Upvotes: 0

Views: 631

Answers (5)

David Heffernan
David Heffernan

Reputation: 612934

const char* append(const char* s1, const char* s2) {
    string s(s1);
    s += s2;
    return s.c_str();
}

The variable s is local to the function. It is destroyed when the function returns. That means that the value that you return, s.c_str(), points to memory that has been deallocated. De-referencing that memory results in undefined behaviour.

The rule with c_str() is, loosely put, that the value it returns is guaranteed to be valid until either the string object is modified or destroyed.

Simply put, you should stop using C strings unless you need to use them for interop. Your function should be:

string append(const string& s1, const string& s2)
{
    return s1 + s2;
}

Upvotes: 1

timrau
timrau

Reputation: 23058

Because in append(), you returned s.c_str(); then, s is destructed, which means that the pointer returned is invalidated immediately.

Let append() return std::string to solve this issue.

std::string append(const char* s1, const char* s2) {
    return std::string(s1).append(s2);
}

void foo() {
    std::string total = append("abc", "def");
    cout << total;
}

Upvotes: 6

triclosan
triclosan

Reputation: 5714

return s.c_str(); : you return pointer obtained from temporary variable s.

You may fix your problem in two ways -

  1. Return std::string by value from append.
  2. Pass to append pointer to fill it with data -
void append(const char* s1, const char* s2, char* out) {
  string s(s1);
  s += s2;
  strncpy(out, s.c_str(), s.size()+1);
}

void foo() {
  char total[7] = {0}; //should be enough to carry appended string + '\0'
  append("abc", "def", total);
  cout<<total;
}

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

You are returning a pointer from append() that is not valid when the function returns.

string s(s1);

defines a object in append(). It is destroyed when you return from the function. Hence, the returned value of s.c_str() is not valid in foo.

You can change your code to be:

string append(const char* s1, const char* s2) {
    string s(s1);
    s += s2;
    return s;
}

void foo() {
    string total = append("abc", "def");
    cout<<total;
}

That should work.

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234685

Undefined Behaviour. c_str is only valid for the lifetime of s (and only then if s is not modified in any way). Once append has returned, s is out of scope. Boom!

One fix is to have append return a std::string.

Upvotes: 4

Related Questions