user1006322
user1006322

Reputation: 51

visual studio 2008 sp1 std::string::c_str() err

i had met same situation in my project.
The following code were similarly reproduced.

#include <iostream>
#include <vector>
using namespace std;


class METHOD
{
public:
vector<METHOD*> m_arg;
string name;
string getName()
{
    return name;
}
METHOD()
{

}
METHOD(string n)
{
    name = n;
}
};

class PF : public METHOD
{
public:
PF(){};
};

void main()
{


PF p;
p.m_arg.push_back(new METHOD(string("a")));
p.m_arg.push_back(new METHOD(string("b")));
p.m_arg.push_back(new METHOD(string("c")));

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    const char* ccs = p.m_arg[i]->getName().c_str();  //PROBLEM POINT

    size_t ss = strlen(ccs);
}

}

the problem is //PROBLEM POINT
the return address of c_str() can't be assigned to const char* ccs.
in debugger, the css assigned memory address of return of c_str(), but css's value is "" and it work same as ""

but the next code is working as expected.

    string str("ok");
const char* ckk = str.c_str();

after this code, ckk points after str.c_str() returnning addres, and ckk's value in debugger is "ok"

the same problem is occuring in std::wstring, wchar_t, unicode.

why did this problem occur?
who knows? help me plz~

ADD: thanks to mystical i solve the problem same way. but this solution also work OK.

    for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string& strr = p.m_arg[i]->getName();
    const char* ccs = strr.c_str();
    size_t ss = strlen(ccs);
}

so i think the return value of getName() is live until the loop } closed.
but interestingly, the next is don't work

    for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string* strr = &p.m_arg[i]->getName();
    const char* ccs = strr->c_str();
    size_t ss = strlen(ccs);
}

the css is 'dangling' and also strr is ""
i've dazed and confused!

Upvotes: 1

Views: 1374

Answers (1)

Mysticial
Mysticial

Reputation: 471229

In your getName() function:

string getName()
{
    return name;
}

The string that is returned is a copy of the original. It becomes an intermediate in the following expression:

const char* ccs = p.m_arg[i]->getName().c_str();

When the expression ends, that intermediate is destroyed. Therefore invalidating the pointer returned by c_str(). The result is that ccs becomes a dangling pointer.

The reason why this works:

string str("ok");
const char* ckk = str.c_str();

is because str is not an intermediate.

To make it work, change your loop to this:

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string str = p.m_arg[i]->getName()
    const char* ccs = str.c_str();

    size_t ss = strlen(ccs);
}

EDIT : To answer your new question:

The reason why this doesn't work:

string* strr = &p.m_arg[i]->getName();

is the same as before. getName() returns an intermediate. You then take the address of this and assign it to strr. The intermediate is destroyed after the statement, so strr becomes a dangling pointer as in the first case.

Upvotes: 4

Related Questions