C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

strange string-behaviour

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Enrico Righes
Guest





PostPosted: Sat Jan 17, 2004 3:11 am    Post subject: strange string-behaviour Reply with quote



hi there

given following simple code:

#include <string>
#include <iostream>

using namespace std;

string foo(string s)
{
return s + " z";
}

int main()
{
const char *s1 = foo("a").c_str();
string s2 = foo("b"); (1)

cout << s1 << endl;
cout << s2.c_str() << endl; (2)
}

The output rather than
a z
b z
it is (Linux g++ 3.3.1 & VC++ 6.0)
b z
b z

In VC++ Debug modus without lines (1) & (2) the output is only junk
(seems that the string-data is deallocated).

Can anybody explain this? Thx in advance!
Enrico

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jack Klein
Guest





PostPosted: Sat Jan 17, 2004 11:05 am    Post subject: Re: strange string-behaviour Reply with quote



On 16 Jan 2004 22:11:33 -0500, [email]righes (AT) freenet (DOT) de[/email] (Enrico Righes) wrote
in comp.lang.c++.moderated:

Quote:
hi there

given following simple code:

#include #include
using namespace std;

string foo(string s)
{
return s + " z";
}

int main()
{
const char *s1 = foo("a").c_str();

Here you have created a temporary string object and used the c_str()
member function to have it generate a C style string, an array of two
characters 'a' and ''. But this is a temporary string object. Its
lifetime ends, and its destructor is called, at the end of the
statement. Your pointer s1 is now invalid, pointing to an object
whose lifetime has ended. Any use of this pointer after the temporary
string has been destroyed, which is at the semicolon ending the
assignment statement, produces undefined behavior.

Quote:
string s2 = foo("b"); (1)

cout << s1 << endl;
cout << s2.c_str() << endl; (2)
}

The output rather than
a z
b z
it is (Linux g++ 3.3.1 & VC++ 6.0)
b z
b z

It just so happens that the new string s2 happens to reuse the memory
just used to hold the temporary string created in the line above it.
There is no requirement in the C++ standard that says this must
happen, but given the way many compilers manage memory it is not
surprising.

Quote:
In VC++ Debug modus without lines (1) & (2) the output is only junk
(seems that the string-data is deallocated).

Yes the string data is deallocated at the ; ending the statement
assigning to the pointer s1. So it becomes a dangling pointer. That
is the way temporary object work, unless they are bound to a constant
reference. They disappear at the end of the statement.

Quote:
Can anybody explain this? Thx in advance!
Enrico

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ivan Vecerina
Guest





PostPosted: Sat Jan 17, 2004 11:07 am    Post subject: Re: strange string-behaviour Reply with quote



"Enrico Righes" <righes (AT) freenet (DOT) de> wrote

Hi Enrico,

Quote:
const char *s1 = foo("a").c_str();
This line of code is the source of the bug:

The pointer returned by c_str() can only be used as long
as the std::string object isn't modified or destroyed.

foo("a") returns a temporary string object that will
be destroyed at the end of the statement (at the Wink.
From then on, accessing data pointed to by s1 leads
to undefined behavior.

Quote:
cout << s1 << endl;

Whenever c_str() is called, one has to make sure that
the returned pointer isn't used beyound the lifetime
of the string object (or after the string is modified).
Storing the result of c_str() in a pointer variable
is almost always a bad idea.

[ This is the reason why std::string does not provide
an *implicit* conversion to "const char*", as other
popular string classes do: it is too dangerous. ]

Quote:
The output rather than
a z
b z
it is (Linux g++ 3.3.1 & VC++ 6.0)
b z
b z
....
Can anybody explain this? Thx in advance!

It seems that the second string defined in your program
just happened to be allocated at the same address as s1.


hth,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Maeder
Guest





PostPosted: Sat Jan 17, 2004 11:29 pm    Post subject: Re: strange string-behaviour Reply with quote

[email]righes (AT) freenet (DOT) de[/email] (Enrico Righes) writes:

Quote:
#include <string
#include

[Unrelated to your problem:]

#include
is missing here, or the overload of operator<< for char const * may not
be available below, which would mean that the overload for void const *
would be used.


Quote:
using namespace std;

string foo(string s)
{
return s + " z";
}

int main()
{
const char *s1 = foo("a").c_str();
[snip]
cout << s1 << endl;

You are calling c_str() on a string object; this string object is then
immediately destructed.

According to the Standard (21.3.6), using the return value of c_str() after
"any subsequent call to a non-const member function" of the string object
has undefined behavior. The destructor is such a non-const member function.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Peter Kragh
Guest





PostPosted: Sat Jan 17, 2004 11:32 pm    Post subject: Re: strange string-behaviour Reply with quote

Enrico Righes wrote:
Quote:
int main()
{
const char *s1 = foo("a").c_str();
string s2 = foo("b"); (1)

cout << s1 << endl;
cout << s2.c_str() << endl; (2)
}

The output rather than
a z
b z
it is (Linux g++ 3.3.1 & VC++ 6.0)
b z
b z

In VC++ Debug modus without lines (1) & (2) the output is only junk
(seems that the string-data is deallocated).

Can anybody explain this? Thx in advance!

I'll try.

The problem is this line of code:

const char *s1 = foo("a").c_str();

Two things to notice: 1) The foo function creates a *temporary* instance of
a string class (i.e. at the end of the expression, the strings destructor is
called). 2) c_str() *doesn't copy* the contents of the string.

The result: s1 points to some garbage.

HTH

- Peter


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Sat Jan 17, 2004 11:32 pm    Post subject: Re: strange string-behaviour Reply with quote

In message <19687458.0401160654.26295813 (AT) posting (DOT) google.com>, Enrico
Righes <righes (AT) freenet (DOT) de> writes
Quote:
hi there

given following simple code:

#include #include
using namespace std;

string foo(string s)
{
return s + " z";
}

int main()
{
const char *s1 = foo("a").c_str();

c_str() provides a char[] based on the value of the string object which
is only valid until something changes the string. Unfortunately the
string returned by foo() is a temporary and disappears at the end of the
above statement. The result is that s1 becomes a hanging pointer and
dereferencing it will have undefined behaviour.

Quote:
string s2 = foo("b"); (1)

This one, in itself is fine, but as you have already exercised undefined
behaviour the result will also be undefined (UB permeates through code
from the point where it happens)

Quote:

cout << s1 << endl;
cout << s2.c_str() << endl; (2)

BTW, unless you have a real reason to force flushing of a stream, use
'n' instead of endl.

Quote:
}

The output rather than
a z
b z
it is (Linux g++ 3.3.1 & VC++ 6.0)
b z
b z
Yes, clearly they are recycling the space for the temporary, as they

are fully entitled to do.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Mang
Guest





PostPosted: Sat Jan 17, 2004 11:40 pm    Post subject: Re: strange string-behaviour Reply with quote



Enrico Righes schrieb:

Quote:


[snip]

Quote:


int main()
{
const char *s1 = foo("a").c_str();

Here, the function foo("a") returns a temporary string. c_str() extracts
the information of the string as C-style array and initializes s1 with
it, but then the string dies (and along with it the memory s1 points
to). s1 points to invalid memory after the expression.


Quote:

string s2 = foo("b"); (1)

Here you copy initialize a new string from the temporary created by
foo("b"). s2 will allocate its own memory to store the string
information.


Quote:


cout << s1 << endl;

KaBoom. s1 points to invalid memory - undefined behavior


Quote:

cout << s2.c_str() << endl; (2)
}

safe, s2 owns the memory.


BTW, you try to output char const*, so you have to #include additionally.


regards,

Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
DarkSpy
Guest





PostPosted: Sun Jan 18, 2004 11:21 am    Post subject: Re: strange string-behaviour Reply with quote

at 16 Jan 2004 22:11:33 -0500 , [email]righes (AT) freenet (DOT) de[/email] (Enrico Righes)
wrote:

Quote:
{
const char *s1 = foo("a").c_str();
foo("a") using copy constructor to new a string.


Quote:
string s2 = foo("b"); (1)
and foo("b")'s copy constructor is new a string, but the "b" 's bytes

is too small to new on old address of foo("a");


[comp.lang.c++]
[comp.lang.c++.moderated]
DarkSpy, A C++ MadDog. :-)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.