string/stringstream memory management

E

Ellarco

Im sorry for asking a question that is surely in the archives somewhere, but
I have been unable to locate it.

Its about string memory management. I need to dynamically construct a
C-style string and was planning to go about it this way;

char* foo()
{
std::stringstream ss;
ss << ...
std::string s = ss.str();
char* c = s.c_str();
return c;
}

void main()
{
char* c = foo();
// work with c
delete(c);
}

What am I doing wrong? Should I be deleting stuff somewhere? Will the foo
return a pointer to some out of scope memory - should it be;

char* foo()
{
std::stringstream* ss = new std::stringstream();
*ss << ...
std::string s = ss->str();
delete(ss);
char* c = s.c_str();
return c;
}

Am I deleting too much? ...

Thanks for any guidance you can offer.

El.
 
G

Gianni Mariani

Ellarco said:
Im sorry for asking a question that is surely in the archives somewhere, but
I have been unable to locate it.

This one is a classic -
Its about string memory management. I need to dynamically construct a
C-style string and was planning to go about it this way;

That usually means use of new
char* foo()
{
std::stringstream ss;
^^^^ defined automatic - life of object is life of function
ss << ...
std::string s = ss.str();
^^^^ defined automatic - life of object is life of function
char* c = s.c_str();
^^^^ s.c_str() did not copy or allocate new memory for this
return c;
^^^^ Oops - returning a pointer to memory that is just about to be
deleted ...
}

void main()
{
char* c = foo();
^^^^ c is pointing to memory that is unallocated
// work with c
delete(c);
^^^^ trying to deallocate a pointer that is not allocated bad bad bad
}

What am I doing wrong? Should I be deleting stuff somewhere? Will the foo
return a pointer to some out of scope memory - should it be;

char* foo()
{
std::stringstream* ss = new std::stringstream();
*ss << ...
std::string s = ss->str();
delete(ss);
^^^^ It's not your responsibility to delete this, s will do it when it
gets destroyed.
 
R

Ron Natalie

char* c = s.c_str();

First, this shouldn't even compile. c_str() is returns const char*.

The return value of c_str() becomes invalid as soon as a non-const member
(including the destructor), get's invoked. S is destroyed as soon as the
function exits so the value returned is invalid by the time it reaches the
caller.

You could return a copy.
char* c = new char[s.size()+1];
strcpy(c, s.c_str());
return c;
void main()

main must return int.
delete(c);

Delete is not a function. You don't need the parens. Further,
Since your intent is that c points to an array allocation, the proper
delete is:
delete [] c;
std::stringstream* ss = new std::stringstream();
*ss << ...
std::string s = ss->str();
delete(ss);

This is just an elaborate way of doing the same thing you had before.
It's not the stringstream that was the problem, it was what you did with
the string called "s" afterwoard.

Why not just return a string. It's usually easier when you need a const char*
out of a string to just use c_str() at the last possible moment. Frequently, the
lifetime of ths string is such that you don't have to wory about making a copy
of the c_str() value because your string persists longer than the char* is needed.
 
F

Frank Schmitt

Im sorry for asking a question that is surely in the archives somewhere, but
I have been unable to locate it.

Its about string memory management. I need to dynamically construct a
C-style string and was planning to go about it this way;

char* foo()
{
std::stringstream ss;

use std::eek:stringstream
ss << ...
std::string s = ss.str();
char* c = s.c_str();
return c;
}

here, s goes out of scope and is destroyed - c points to never-neverland.
void main()

main returns int
{
char* c = foo();
// work with c
delete(c);
}

You can either create a new C-style string in foo() using strcpy(), or
you can (much preferable IMHO) just return a std::string from foo:

std::string foo() {
std::eek:stringstream ss;
ss << ...;
return ss.str();
}

If you insist on using C-style strings, create one with new[] in
foo, strcpy() to it, and delete[] it in main().

HTH & kind regards
frank
 
K

Karl Heinz Buchegger

Ellarco said:
Im sorry for asking a question that is surely in the archives somewhere, but
I have been unable to locate it.

Its about string memory management. I need to dynamically construct a
C-style string and was planning to go about it this way;

char* foo()
{
std::stringstream ss;
ss << ...
std::string s = ss.str();
char* c = s.c_str();
return c;
}

Bad idea.
AT the moment this function terminates, the object s is killed.
And since the object s is killed, so is the buffer it handed out
to you through c_str().

void main()

int main()
{
char* c = foo();
// work with c
delete(c);

wrong syntax. Must be delete [] c;
Please: always cut and paste code, don't write it directly in your
newsreader. Otherwise we are hunting bugs which simply are not there
in your real program.

Well. Did you allocate something? Did your documentation of c_str()
tell you to delete the buffer?
The answer is no in both cases. So, no, you don't have to delete
anything (but that will change in a short while :)

As you have seen, you can't return what c_str() gives to you, since
the object itself goes out of scope and hence the buffer is deleted,
while doing so. From this it follows that you first have to create
a copy of the C-style string:

char* foo()
{
....
std::string s = ss.str();

char* c = new char [ s.size() + 1 ];
strcpy( c, s.c_str() );
return c;
}

Now foo hands out a dynamically allocated buffer which is filled with
a copy of what c_str() handed out.
And since this buffer was allocated with new[], you have to delete[]
it somewhere.

int main()
{
char* cc = foo();
....
delete [] c;
}
 
E

Ellarco

Karl Heinz Buchegger said:
Im sorry for asking a question that is surely in the archives somewhere, but
I have been unable to locate it.

Its about string memory management. I need to dynamically construct a
C-style string and was planning to go about it this way;

char* foo()
{
std::stringstream ss;
ss << ...
std::string s = ss.str();
char* c = s.c_str();
return c;
}

Bad idea.
AT the moment this function terminates, the object s is killed.
And since the object s is killed, so is the buffer it handed out
to you through c_str().

void main()

int main()
{
char* c = foo();
// work with c
delete(c);

wrong syntax. Must be delete [] c;
Please: always cut and paste code, don't write it directly in your
newsreader. Otherwise we are hunting bugs which simply are not there
in your real program.

Well. Did you allocate something? Did your documentation of c_str()
tell you to delete the buffer?
The answer is no in both cases. So, no, you don't have to delete
anything (but that will change in a short while :)

As you have seen, you can't return what c_str() gives to you, since
the object itself goes out of scope and hence the buffer is deleted,
while doing so. From this it follows that you first have to create
a copy of the C-style string:

char* foo()
{
....
std::string s = ss.str();

char* c = new char [ s.size() + 1 ];
strcpy( c, s.c_str() );
return c;
}

Now foo hands out a dynamically allocated buffer which is filled with
a copy of what c_str() handed out.
And since this buffer was allocated with new[], you have to delete[]
it somewhere.

int main()
{
char* cc = foo();
....
delete [] c;
}

Thanks to all. Youve cleared it up. To summarise what youve said, everything
is as normal. I had an idea in my head that string behaved in some sort of
anomalas (in terms of memory) way - idiot. Apologies for the buggy code I
posted, and thanks again.

El.
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top