using a char* pointer returned by c_str after a string has beendeallocated

C

C++Liliput

I have a class of the type

class A
{
private:
std::string data;
.......
public:
const char* toString();
};

A::A(const char* s):data(s) {}
const char* A::toString() { return data.c_str();)

I have the following scenario in the code:

A* pObj = new A("New");
const char* str = A -> toString();
............
............
delete pObj;
printf("The string representation of A is %s", str);

Now I know that the above code is probably wrong because I use the
char pointer returned by the c_str() function after the object
(containing a string member variable) has been deallocated. But I am
interested to know why. Is it because the c_str() returns the internal
char pointer of the string object? c_str() returns a null terminated
string which means that probably a copy of the internal char buffer
terminated with a null character is returned to the user. But if that
is the case, it should be the responsibility of the user to explicitly
deallocate the char pointer after it is not being used. But we don't
do it do we? So I am a bit confused about what exactly happens.
 
I

Ian Collins

C++Liliput said:
I have a class of the type

class A
{
private:
std::string data;
.......
public:
const char* toString();
};

A::A(const char* s):data(s) {}
const char* A::toString() { return data.c_str();)

I have the following scenario in the code:

A* pObj = new A("New");
const char* str = A -> toString();
............
............
delete pObj;
printf("The string representation of A is %s", str);

Now I know that the above code is probably wrong because I use the
char pointer returned by the c_str() function after the object
(containing a string member variable) has been deallocated. But I am
interested to know why. Is it because the c_str() returns the internal
char pointer of the string object? c_str() returns a null terminated
string which means that probably a copy of the internal char buffer
terminated with a null character is returned to the user. But if that
is the case, it should be the responsibility of the user to explicitly
deallocate the char pointer after it is not being used. But we don't
do it do we? So I am a bit confused about what exactly happens.

The exact details are unimportant, what matters is data.c_str() returns
a pointer to a buffer owned by data. So when the object containing data
is deleted, data is destroyed and the buffer becomes invalid.
 
B

Boris

[...]terminated with a null character is returned to the user. But if
that
is the case, it should be the responsibility of the user to explicitly
deallocate the char pointer after it is not being used. But we don't
do it do we? So I am a bit confused about what exactly happens.

If it was the responsibility of the user to deallocate the buffer the
return type of c_str() would have better been std::auto_ptr<const char*>.
That way it would have been obvious that ownership is passed to the
caller. If you don't get a smart pointer you can basically assume that
ownership is not passed to the caller (at least that's the rule I try to
follow; this might not be true for every function of course).

Boris
 
J

James Kanze

The exact details are unimportant, what matters is
data.c_str() returns a pointer to a buffer owned by data. So
when the object containing data is deleted, data is destroyed
and the buffer becomes invalid.

Right. It's a question of contract. In fact, in the case of
std::string, the contract is that the pointer returned by
c_str() is valid until the next non-const function is called,
and no longer. Just reading a character with [] can
(theoretically, at least, but also practically, with g++, for
example) invalid it.

If he needs the pointer for a longer period of time, he'll have
to arrange to allocate the memory himself somehow, and use
std::string::copy to put the string into it.
 
J

James Kanze

[...]terminated with a null character is returned to the user. But if
that
is the case, it should be the responsibility of the user to explicitly
deallocate the char pointer after it is not being used. But we don't
do it do we? So I am a bit confused about what exactly happens.
If it was the responsibility of the user to deallocate the
buffer the return type of c_str() would have better been
std::auto_ptr<const char*>. That way it would have been
obvious that ownership is passed to the caller. If you don't
get a smart pointer you can basically assume that ownership
is not passed to the caller (at least that's the rule I try to
follow; this might not be true for every function of course).

It's not true of the new operator:). Nor of the frequently
available function strdup(). But I agree that it is a fairly
good general rule. Except: you probably don't want to apply it
to functions returning pointers to entity objects (which manage
their own lifetime), and you generally don't want to return
dynamically allocated values in the first place.
 
P

Pete Becker

[...]terminated with a null character is returned to the user. But if
that
is the case, it should be the responsibility of the user to explicitly
deallocate the char pointer after it is not being used. But we don't
do it do we? So I am a bit confused about what exactly happens.
If it was the responsibility of the user to deallocate the
buffer the return type of c_str() would have better been
std::auto_ptr<const char*>. That way it would have been
obvious that ownership is passed to the caller. If you don't
get a smart pointer you can basically assume that ownership
is not passed to the caller (at least that's the rule I try to
follow; this might not be true for every function of course).

It's not true of the new operator:). Nor of the frequently
available function strdup(). But I agree that it is a fairly
good general rule. Except: you probably don't want to apply it
to functions returning pointers to entity objects (which manage
their own lifetime), and you generally don't want to return
dynamically allocated values in the first place.

And, of course, you don't want to apply it to the case under
discussion, because the pointer in question points to an array, not a
single element. auto_ptr doesn't do delete[].
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top