Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > ostringstream output to C-string

Reply
Thread Tools

ostringstream output to C-string

 
 
Fab
Guest
Posts: n/a
 
      03-24-2008
Hi C++ experts,
I'm using std:stringstream in my program to format a string. In my
unit tests I use it quite extensively to generate expected results
that I then compare with a predefined string.

The problem is that this code does something wrong:

std:stringstream os;
os << "Hello world";
const char * const produced = os.str().c_str();
if (strcmp(produced, "Hello world") == 0) {...}

In particular, the 'produced' buffer is invalid.
On Linux and Mac OS X the program run and any access to 'produced'
buffer, does not report any error, but if you run a test program with
valgrind, Guard Malloc or any other memory checker tools, all the
tools report some problems.

The workaround to this problem is to generate a temporary variable to
store a reference to the the std::string produced by os.str(). In this
case everything works as expected:
std:stringstream os;
os << "Hello world";
const std::string & tempString(os.str());
const char * const produced = os.str().c_str();
if (strcmp(produced, "Hello world") == 0) {...}

Is it because os.str().c_str() generates a temporary std::string to
store the produced string, and c_str() returns a pointer to this temp
object? Shouldn't temp object get disposed when exiting the scope?
Does it mean that this temp string's scope is only the 'produced'
assignment and after that is no longer valid?

What's your opinion on that?
F.
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      03-24-2008
Fab wrote:
> I'm using std:stringstream in my program to format a string. In my
> unit tests I use it quite extensively to generate expected results
> that I then compare with a predefined string.
>
> The problem is that this code does something wrong:
>
> std:stringstream os;
> os << "Hello world";
> const char * const produced = os.str().c_str();
> if (strcmp(produced, "Hello world") == 0) {...}
>
> In particular, the 'produced' buffer is invalid.
> On Linux and Mac OS X the program run and any access to 'produced'
> buffer, does not report any error, but if you run a test program with
> valgrind, Guard Malloc or any other memory checker tools, all the
> tools report some problems.
>
> The workaround to this problem is to generate a temporary variable to
> store a reference to the the std::string produced by os.str(). In this
> case everything works as expected:
> std:stringstream os;
> os << "Hello world";
> const std::string & tempString(os.str());
> const char * const produced = os.str().c_str();
> if (strcmp(produced, "Hello world") == 0) {...}


This is nothing different from the other code, from the language
point of view. The expression that used to initialise 'produced'
can still create another temporary, which is going to be destroyed
at the end of initialising 'produced', thus making 'procuded'
an invalid pointer. You just get lucky here and not the first
time around.

What you want to do, perhaps is

const char* const procuded = tempString.c_str();

Then you're using the actual temporary object that 'tempString'
is bound to, and which will survive as long as 'tempString' does.

> Is it because os.str().c_str() generates a temporary std::string to
> store the produced string, and c_str() returns a pointer to this temp
> object?


Yes, pretty much.

> Shouldn't temp object get disposed when exiting the scope?


Not sure how to answer this question (about the scope) because I
don't understand what you're asking. The temp object created in
the expression used to evaluate 'produced' survives only until
the 'produced' gets fully initialised.

> Does it mean that this temp string's scope is only the 'produced'
> assignment and after that is no longer valid?


It's not assignment, it's initialisation. And, yes, it's destroyed
right after 'produced' is initialised.

> What's your opinion on that?


No opinion. It's all according to the written rules.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      03-24-2008
Fab schrieb:
> Hi C++ experts,
> I'm using std:stringstream in my program to format a string. In my
> unit tests I use it quite extensively to generate expected results
> that I then compare with a predefined string.
>
> The problem is that this code does something wrong:
>
> std:stringstream os;
> os << "Hello world";
> const char * const produced = os.str().c_str();
> if (strcmp(produced, "Hello world") == 0) {...}
>
> In particular, the 'produced' buffer is invalid.
> On Linux and Mac OS X the program run and any access to 'produced'
> buffer, does not report any error, but if you run a test program with
> valgrind, Guard Malloc or any other memory checker tools, all the
> tools report some problems.
>
> The workaround to this problem is to generate a temporary variable to
> store a reference to the the std::string produced by os.str(). In this
> case everything works as expected:
> std:stringstream os;
> os << "Hello world";
> const std::string & tempString(os.str());
> const char * const produced = os.str().c_str();
> if (strcmp(produced, "Hello world") == 0) {...}
>
> Is it because os.str().c_str() generates a temporary std::string to
> store the produced string, and c_str() returns a pointer to this temp
> object? Shouldn't temp object get disposed when exiting the scope?


Temporary objects are destroyed at the end of the statement. So your
'produced' variable is initialized, then the temporary string is destroyed,
and the pointer to the buffer containing the string becomes invalid.

> What's your opinion on that?


Don't use c_str(), compare the string directly:

if (os.str() == "Hello world") { /*...*/ }

--
Thomas
http://www.netmeister.org/news/learn2quote.html
++++++++++[>+++++<-]>++.--.
 
Reply With Quote
 
Fab
Guest
Posts: n/a
 
      03-24-2008
Well, thanks to all for the answer... and yes, as Victor pointed out,
my example was wrong (I managed to copy the wrong part of the code,
and the C-string assignment is supposed to use the 'tempString'
std::string.
Ok, so, temporary objects are destroyed after the initialization.
But in this code:
const std::string & tempString(os.str());
tempString is a reference to a temp object too, right? Why now the
temp object is still valid? Does it mean the compiler do not destroy
it because it knows there is still one reference to it? Or simply
'tempString' *IS* the temp object?

So, in these two cases:
const std::string & tempString(os.str());
and
const std::string tempString(os.str());

the second tempString is a copy of the temp object (that perhaps share
the same buffer if std::string uses reference counting), and the first
is the temp object itself?

Fab

On Mar 24, 11:40*am, "Thomas J. Gritzan" <Phygon_ANTIS...@gmx.de>
wrote:
> Fab schrieb:
>
>
>
> > Hi C++ experts,
> > I'm using std:stringstream in my program to format a string. In my
> > unit tests I use it quite extensively to generate expected results
> > that I then compare with a predefined string.

>
> > The problem is that this code does something wrong:

>
> > * * std:stringstream os;
> > * * os << "Hello world";
> > * * const char * const produced = os.str().c_str();
> > * * if (strcmp(produced, "Hello world") == 0) {...}

>
> > In particular, the 'produced' buffer is invalid.
> > On Linux and Mac OS X the program run and any access to 'produced'
> > buffer, does not report any error, but if you run a test program with
> > valgrind, Guard Malloc or any other memory checker tools, all the
> > tools report some problems.

>
> > The workaround to this problem is to generate a temporary variable to
> > store a reference to the the std::string produced by os.str(). In this
> > case everything works as expected:
> > * * std:stringstream os;
> > * * os << "Hello world";
> > * * const std::string & tempString(os.str());
> > * * const char * const produced = os.str().c_str();
> > * * if (strcmp(produced, "Hello world") == 0) {...}

>
> > Is it because os.str().c_str() generates a temporary std::string to
> > store the produced string, and c_str() returns a pointer to this temp
> > object? Shouldn't temp object get disposed when exiting the scope?

>
> Temporary objects are destroyed at the end of the statement. So your
> 'produced' variable is initialized, then the temporary string is destroyed,
> and the pointer to the buffer containing the string becomes invalid.
>
> > What's your opinion on that?

>
> Don't use c_str(), compare the string directly:
>
> if (os.str() == "Hello world") { /*...*/ }
>
> --
> Thomashttp://www.netmeister.org/news/learn2quote.html
> ++++++++++[>+++++<-]>++.--.


 
Reply With Quote
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      03-24-2008
Fab wrote:
> Well, thanks to all for the answer... and yes, as Victor pointed out,
> my example was wrong (I managed to copy the wrong part of the code,
> and the C-string assignment is supposed to use the 'tempString'
> std::string.
> Ok, so, temporary objects are destroyed after the initialization.
> But in this code:
> const std::string & tempString(os.str());
> tempString is a reference to a temp object too, right? Why now the
> temp object is still valid? Does it mean the compiler do not destroy
> it because it knows there is still one reference to it? Or simply
> 'tempString' *IS* the temp object?


It's an exception to the rule.
The C++ standard says, that a temporary object, that is bound to a
reference, is not destroyed as long as the reference is in scope.

So by binding the temporary object to the reference, you coupled the
lifetime of both.

> So, in these two cases:
> const std::string & tempString(os.str());
> and
> const std::string tempString(os.str());
>
> the second tempString is a copy of the temp object (that perhaps share
> the same buffer if std::string uses reference counting), and the first
> is the temp object itself?


Yes, the second tempString is initilized (copy constructed) from the
temporary string returned by os.str(), unless the compiler uses RVO (return
value optimization) to remove this copy.

>

[fullquote removed]

Please don't toppost, and please don't quote signatures. Read the link in
my signature to learn how to quote.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
There are no bugs, and they have been fixed!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: using ZLIB to compress std::ostringstream? Mike C++ 1 08-03-2003 06:50 PM
Re: ? How to clear ostringstream buffer Mark Warren C++ 3 07-23-2003 10:12 AM
vector of ostringstream Alex Vinokur C++ 4 07-14-2003 02:36 AM
Re: std::ostringstream unexpected behavior with .net 2003. Russell Hanneken C++ 0 06-25-2003 10:22 PM
Re: std::ostringstream unexpected behavior with .net 2003. Victor Bazarov C++ 0 06-25-2003 10:20 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57