473,383 Members | 1,805 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

I am mystified... need help with STL.

Hi all,

I'm having some trouble understanding the behavior of std::ostringstream.
(I'm using Visual Studio .Net & STL port 4.5.3). I'll appreciate if someone
can give me a little explanation of this behavior and how it is possible...

Here's my code

//////////////////////////
#include <stdio.h>
#include <ostream>

void func( const char* s )
{
printf( "func: [%u], [%s]\n", s, s );
}

void main( void )
{
std::ostringstream stream;
stream << "Hello World";
const char* s = stream.str().c_str();
printf( "main: [%u], [%s]\n", s, s );
func( stream.str().c_str() );
}
////////////////////////////////

And here's my result:

main: [3290280], []
func: [3290280], [Hello World]

Thankx a lot!
Ben Thomas.
Jul 19 '05 #1
7 2286
Ben Thomas wrote:
Hi all,

I'm having some trouble understanding the behavior of std::ostringstream.
(I'm using Visual Studio .Net & STL port 4.5.3). I'll appreciate if someone
can give me a little explanation of this behavior and how it is possible...

Here's my code

//////////////////////////
#include <stdio.h>
#include <ostream>
What about <sstream>?

void func( const char* s )
{
printf( "func: [%u], [%s]\n", s, s );
This invokes undefined behavior. The %u format specifier is for unsigned
ints only. You are passing it a const char *. This is a good example of
why you should not use printf or any function or language construct that
defeats type-checking.
}

void main( void )
main returns int. void is not and never has been an acceptable return
type for main.
{
std::ostringstream stream;
stream << "Hello World";
const char* s = stream.str().c_str();
My best guess is that ostringstream::str() returns by value (strangely,
I can't find this information in either Stroustrup or Josuttis). That
means you get a temporary std::string, which you then invoke c_str() on.
However, the temporary goes out of scope after this statement completes,
and the pointer returned from c_str() is no longer valid. Try this instead:

std::string tmp = stream.str();
const char* s = tmp.c_str();
printf( "main: [%u], [%s]\n", s, s );
Undefined behavior again.
func( stream.str().c_str() );


In this case, the same thing happens except that the temporary does not
go out of scope until the function completes.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #2

"Kevin Goodsell" <us*********************@neverbox.com> wrote in message news:AA68b.8848
printf( "func: [%u], [%s]\n", s, s );


This invokes undefined behavior. The %u format specifier is for unsigned
ints only. You are passing it a const char *. This is a good example of
why you should not use printf or any function or language construct that
defeats type-checking.


Yes, if he wants to inspect the pointer, the way to do it is:
printf("func [%p],[%s]\n", (void*)s, s);

Jul 19 '05 #3
Ron Natalie wrote:
"Kevin Goodsell" <us*********************@neverbox.com> wrote in
message news:AA68b.8848
printf( "func: [%u], [%s]\n", s, s );


This invokes undefined behavior. The %u format specifier is for
unsigned ints only. You are passing it a const char *. This is a
good example of why you should not use printf or any function or
language construct that defeats type-checking.


Yes, if he wants to inspect the pointer, the way to do it is:
printf("func [%p],[%s]\n", (void*)s, s);


To be a complete nitpicker, the C++ way to do it is:
std::cout << "main: [" << static_cast<const void*>(s) << "], [" << s <<
"]" << std::endl;

Or even more nitpicky, we should forget char* altogether, std::string should
be good enough for us C++ types:
std::cout << "main: [" << stream.str() << "]" << std::endl;

^_^

--
Unforgiven

"Most people make generalisations"
Freek de Jonge

Jul 19 '05 #4
Thankx for the answer!

Okay, I have fixed the problem with displaying the pointers value and change
#include<ostream> with #include<sstream> and return 0 in the main function
and it's the same behavior! :)

The solution of a temp variable works! I too first though that it was a
scope problem, that's why I displayed the pointer value. Yet, they are the
same, so scope seems to be okay, only that it's empty in one call and not in
the other. Also, I don't know if there's a difference in scope between the
two kind of call... I have tryed to write a class that reproduce the same
kind of behavior but wasn't able to do so... maybe it's in the many level of
template with STL, but how can you make your class act differently between
this

const char* s = stream.str().c_str();

and this

func( stream.str().c_str() ); // void func( const char* s );

I just can't make sense of it... maybe the problem is elsewhere after all.
Ben Thomas.

"Ron Natalie" <ro*@sensor.com> wrote in message
news:3f***********************@news.newshosting.co m...

"Kevin Goodsell" <us*********************@neverbox.com> wrote in message

news:AA68b.8848
printf( "func: [%u], [%s]\n", s, s );


This invokes undefined behavior. The %u format specifier is for unsigned
ints only. You are passing it a const char *. This is a good example of
why you should not use printf or any function or language construct that
defeats type-checking.


Yes, if he wants to inspect the pointer, the way to do it is:
printf("func [%p],[%s]\n", (void*)s, s);

Jul 19 '05 #5
Ben Thomas wrote:
Thankx for the answer!
Please don't top-post. Re-read section 5 of the FAQ for posting guidelines.

http://www.parashift.com/c++-faq-lite/

Okay, I have fixed the problem with displaying the pointers value and change
#include<ostream> with #include<sstream> and return 0 in the main function
and it's the same behavior! :)

The solution of a temp variable works! I too first though that it was a
scope problem, that's why I displayed the pointer value. Yet, they are the
same,
This proves absolutely nothing.
so scope seems to be okay,
Bad conclusion.
only that it's empty in one call and not in
the other.
It's undefined in one call, and not in the other.
Also, I don't know if there's a difference in scope between the
two kind of call... I have tryed to write a class that reproduce the same
kind of behavior but wasn't able to do so... maybe it's in the many level of
template with STL, but how can you make your class act differently between
this

const char* s = stream.str().c_str();
OK, I'll try to explain again (but I suspect you need to look up
"temporaries" or "temporary objects" in your C++ book).

stream.str() returns by value. This means that the result is copied into
a "temporary object". Now, the ruled for temporary objects state that
they go out of scope at the end of the full expression in which they are
created. A full expression is an expression that is not a sub-expression
of any larger expression, therefore the full expression in this
particular case is the entire statement, minus the semi-colon. That
means that the temporary std::string object containing the result of
stream::str() is GONE once this statement completes. It no longer exists.

Since the pointer returned from std::string::c_str() ceases to be valid
when the std::string is modified or destroyed, your 's' pointer stops
being valid as soon as you initialize it.

and this

func( stream.str().c_str() ); // void func( const char* s );
In this case, the full expression includes the function call. The
function call uses the pointer while it's still valid. As soon as the
function completes, the temporary std::string object goes out of scope
and the pointer is no longer valid - but that's OK this time because you
haven't saved it anywhere.

I just can't make sense of it... maybe the problem is elsewhere after all.


I'm quite sure this IS the problem. I've verified my assumption about
the return type of std::ostringstream::str() by checking the standard.
What you are doing is roughly equivalent to this:

#include <iostream>
#include <cstring>

using namespace std;

class Stupid
{
char *str;
public:
Stupid() : str(new char[20]) { strcpy(str, "this is stupid");
cout << "Constructing a Stupid object" << endl; }
~Stupid() { delete [] str;
cout << "Destroying a Stupid object"
" (and releasing memory)" << endl; }
char *GetPtr() { return str; }
};

int main()
{
char *s = Stupid().GetPtr();

cout << "The string pointed to by s is:\n" << s << endl;

return 0;
}

If you can't see why this is horribly broken, try running it. The object
dies and releases its memory before you even have a chance to use 's'.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #6
So, Ben, if you really want your code to work, just make a few adjustments:

#include <stdio.h>
#include <sstream>
#include <string>

void func( const char* s )
{
printf( "func: [%p], [%s]\n", s, s );
}

void main( void )
{
std::ostringstream stream;
stream << "Hello World";
std::string s = stream.str();
printf( "main: [%p], [%s]\n", s.c_str(), s.c_str() );
func( stream.str().c_str() );
}

That way, you *copy* the temporary object to a new (non-temporary) one, and
it's valid when you call your func function.

Maybe this should help you understand std::ostringstream a little better :-)

BR,
Peter Kragh
Jul 19 '05 #7
Peter Kragh wrote:
So, Ben, if you really want your code to work, just make a few adjustments:

#include <stdio.h>
Deprecated.
#include <sstream>
#include <string>

void func( const char* s )
{
printf( "func: [%p], [%s]\n", s, s );
This is an error, as has already been discussed in this thread. %p only
accepts void*.
}

void main( void )
main must return int. This is required by the C++ standard.
{
std::ostringstream stream;
stream << "Hello World";
std::string s = stream.str();
printf( "main: [%p], [%s]\n", s.c_str(), s.c_str() );
Same error.
func( stream.str().c_str() );
}

That way, you *copy* the temporary object to a new (non-temporary) one, and
it's valid when you call your func function.

Maybe this should help you understand std::ostringstream a little better :-)


-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Sofia | last post by:
My name is Sofia and I have for many years been running a personals site, together with my partner, on a non-profit basis. The site is currently not running due to us emigrating, but during its...
1
by: Tom Yee | last post by:
We just installed SQL Server version 800.194 on a dual processor server equipped with a gigabyte of RAM, running Windows 2000 Server operating system. We set up a few databases with (so far) very...
3
by: Paul Wake | last post by:
http://www.xmission.com/~wake/section27.html now works for me in IE/Win but not in Mozilla/Win (my PowerBook is dead and I'm now using my mother-in-law's PC, which limits my options for checking...
1
by: Joost | last post by:
Hi to all, I have a subform which changes its Sourceobject, using the following expression: Forms!!.SourceObject = "Subform Deposito Mant" and the focus to the desired control, a textbox...
12
by: Chad | last post by:
This was taken from the following: http://groups.google.com/group/comp.lang.c/browse_thread/thread/089dfb62c71802b3/663e9afae83d061c?hl=en#663e9afae83d061c And I quote: "Well, that's also ok...
8
by: turnitup | last post by:
var body = "blah"; document.getElementById("messagebody").innerHTML = body.toString(); results in syntax error!!!! Any ideas?
0
by: U S Contractors Offering Service A Non-profit | last post by:
Brilliant technology helping those most in need Inbox Reply U S Contractors Offering Service A Non-profit show details 10:37 pm (1 hour ago) Brilliant technology helping those most in need ...
8
by: Jim | last post by:
Hi, I am hoping that someone here can help me out on this. The following code works just fine and gives me a nice margin between my image to the left and the text that appears adjacent to it...
5
matheussousuke
by: matheussousuke | last post by:
Hello, I'm using tiny MCE plugin on my oscommerce and it is inserting my website URL when I use insert image function in the emails. The goal is: Make it send the email with the URL...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.