string

E

eastern_strider

Hi,

Is it safe to have a pointer to a string.c_str() created locally inside
a function? For example, would the following code give me headace if a
try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

Thanks,
Oguz
 
B

Bart

eastern_strider said:
Hi,

Is it safe to have a pointer to a string.c_str() created locally inside
a function?
No.

For example, would the following code give me headace if a
try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

You shouldn't do this. You can normally call functions that take a
C-style string without any problems (as long as they don't modify the
string) as these normally just copy the string into their own internal
buffer. However, having pointers to char in your own code is just a bad
idea. Why not just have a string object that holds the string?

Regards,
Bart.
 
D

Default User

eastern_strider said:
Hi,

Is it safe to have a pointer to a string.c_str() created locally
inside a function? For example, would the following code give me
headace if a try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

Yes, it would. str ceases to exist at the end of that scope, and any
memory it allocated is almost suredly deallocated. Otherwise every use
of a string would be memory leak.




Brian
 
T

tugboat90

I'm not quite sure about the memory being deallocated at the end of the
function. I've run into several instances where I've had memory leaks
from CStrings that haven't been deallocated.

If I remember correctly there are functions inside CString to help
clean up. I don't remember the exact function calls, but they were
something to the extent of "EmptyStringContents" and then
"FreeUnusedMemory".
 
L

Larry Smith

tugboat90 said:
I'm not quite sure about the memory being deallocated at the end of the
function. I've run into several instances where I've had memory leaks
from CStrings that haven't been deallocated.

If I remember correctly there are functions inside CString to help
clean up. I don't remember the exact function calls, but they were
something to the extent of "EmptyStringContents" and then
"FreeUnusedMemory".

Please don't top-post...

A C++ std::string is NOT a CString.

CString is Microsoft specific.

std::string does not have cleanup issues.
 
J

Jim Langston

eastern_strider said:
Hi,

Is it safe to have a pointer to a string.c_str() created locally inside
a function? For example, would the following code give me headace if a
try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

Yes and No. It depends on what you plan on doing with the string pointer
after you assign it. The pointer returned to by .c_str() will remain valid
until the std::string is changed somehow (characters added, erased, etc..)
or the std::string goes out of scope. With such limitations it's easy to
get bitten by the data becoming invalid. If you have an extremely good
reason for doing this (and I actually can't think of one), and document it
in code, and know what you're doing, it should be okay, but with all tose
this and that and that, it is safer, IMO, just not to do that.

So the question becomes, *why* would you want to assign the pointer returned
via .c_str() to a variable? For what purpose? It is a constant c-string
and so you can't change the data. So why do you need to keep the pointer
around?
 
G

Greg

eastern_strider said:
Hi,

Is it safe to have a pointer to a string.c_str() created locally inside
a function? For example, would the following code give me headace if a
try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

No, as others have pointed out c becomes a stale pointer as soon as
foo() returns to its caller.

As a rule of thumb, call std::string::c_str() only when passing the
contents of a std::string object to a function that expects a const
char * parameter (such as many POSIX routines). Limiting
std::string-to-C-string-pointer conversions to this one case ensures
that the converted const char * pointer never becomes stale. Otherwise,
just use std::string's consistently throughout the rest of your code.

Greg
 
G

Greg

eastern_strider said:
Hi,

Is it safe to have a pointer to a string.c_str() created locally inside
a function? For example, would the following code give me headace if a
try to use "c" after calling foo() ?

const char *c;

void foo ()
{
string str = "Hello";
c = str.c_str();
}

Yes, this program will have a serious problem: as others have pointed
out c becomes a stale pointer as soon as foo() returns to its caller.

As a rule of thumb, call std::string::c_str() only when passing the
contents of a std::string object to a function that expects a const
char * parameter (such as many POSIX routines). Limiting
std::string-to-C-string-pointer conversions to this one case ensures
that the converted const char * pointer never becomes stale. Otherwise,
just use std::string's consistently throughout the rest of your code.

Greg
 
E

eastern_strider

Hi,

Thanks for all replies. I've just given the sample code for
illustration and what I'm exactly doing is very similar to Greg's
example.

I'm using an external library function which accepts c-style strings as
argument. However, it just keeps a pointer to this argument. That is,
it DOES NOT actually copy it to an internal buffer. So my real use of
c_str() is just like:

MyClass::MyClass()
{
string str = "Hello";
BaseClass::add (str.c_str());
}

Now what "add" does is:

void BaseClass::add (const char *item)
{
item_ptr = item; // item_ptr is a const char* member of BaseClass
}

So this is the whole story. The question is, throughout the rest of the
program, does item_ptr continue to point to a valid location? I
believe I can ensure that explicitly by definining:

string* str = new string ("Hello");

inside my constructor. However, I've been wondering whether such an
explicit allocation is actually necessary in this case.

All answers are very much appreciated.
Oguz
 
F

Florian Stinglmayr

eastern_strider said:
I'm using an external library function which accepts c-style strings as
argument. However, it just keeps a pointer to this argument. That is,
it DOES NOT actually copy it to an internal buffer. So my real use of
c_str() is just like:

MyClass::MyClass()
{
string str = "Hello";
BaseClass::add (str.c_str());
}

Now what "add" does is:

void BaseClass::add (const char *item)
{
item_ptr = item; // item_ptr is a const char* member of BaseClass
}

Why not:

void BaseClass::add (const std::string& item )
{
_sitem = item;
my_ext_library_which_accepts_cstrings(_sitem.c_str());
}
So this is the whole story. The question is, throughout the rest of the
program, does item_ptr continue to point to a valid location?

No, since the std::string "str" gets out of scope and the memory it
contained is deleted. As pointed out earlier.
I believe I can ensure that explicitly by definining:

string* str = new string ("Hello");

You don't have to use pointers. If you pass a C style string to the
constructor of an std::string it automatically creates a copy of the
string.

I urge you to get a C++ book.
 
S

Salt_Peter

eastern_strider said:
Hi,

Thanks for all replies. I've just given the sample code for
illustration and what I'm exactly doing is very similar to Greg's
example.

I'm using an external library function which accepts c-style strings as
argument. However, it just keeps a pointer to this argument. That is,
it DOES NOT actually copy it to an internal buffer. So my real use of
c_str() is just like:

MyClass::MyClass()
{
string str = "Hello";
BaseClass::add (str.c_str());
}

Now what "add" does is:

void BaseClass::add (const char *item)
{
item_ptr = item; // item_ptr is a const char* member of BaseClass
}

So this is the whole story. The question is, throughout the rest of the
program, does item_ptr continue to point to a valid location? I
believe I can ensure that explicitly by definining:

string* str = new string ("Hello");

inside my constructor. However, I've been wondering whether such an
explicit allocation is actually necessary in this case.

item_ptr is not valid. You'll need to manage the allocation of a
std::string. That does not mean you need a heap allocation. You can
keep a const std::string member in MyClass. You'll need to observe
what, if any, ctor is available for that BaseClass.

Now there are 2 issues you need to be aware of: copy ctors and
inheritence.
What follows is not neccessarily correct for you. You may prefer
overiding add(...).

#include <string>

class MyClass : public BaseClass
{
const std::string s_;
public:
MyClass(std::string s) : BaseClass() : s_(s)
{
add(s_.c_str());
}
MyClass(const MyClass& r_copy) : BaseClass(), s_(r_copy.s_) // const
{
add(s_.c_str()); // reseated pointer
}
};

If you need to copy an instance of MyClass, you certainly don't want
the BaseClass pointer (const char* item) to point to the original
instance. If you don't plan to copy at all, disable copy construction.
Better an error than a bug you'll regret.

class MyClass : public BaseClass
{
const std::string s_;
public:
MyClass(std::string s) : BaseClass() : s_(s)
{
add(s_.c_str());
}
MyClass(const MyClass& r_copy); // disabled
};

Lastly: inheritence.
Don't use pointers to BaseClass objects to store MyClass instances if
BaseClass does not have a virtual d~tor. I'm willing to bet that the
BaseClass is using a non-virtual compiler-generated ctor.

Finally, don't use pointers unless you absolutely have to. Always
prefer references.
 
E

eastern_strider

Thanks for your kind! reply, but it seems misleading to me.

Please correct me if I'm wrong but you suggest that:

const char* foo ()
{
std::string str ("Hello");
return str.c_str();
}

int main()
{
const char *c = foo();
// c can be used safely in the rest of the program.
}

I'm not sure that this is as safe as:

const char* foo ()
{
std::string* str = new string ("Hello");
return str->c_str();
}

because in the latter we guarantee that the memory associated with str
will continue to exist even after foo returns. However, in the former
version that memory might be freed once foo returns since str is a
local variable.

Cheers,
Oguz
 
T

tragomaskhalos

Thanks for your kind! reply, but it seems misleading to me.

Please correct me if I'm wrong but you suggest that:

const char* foo ()
{
std::string str ("Hello");
return str.c_str();

}int main()
{
const char *c = foo();
// c can be used safely in the rest of the program.

NOOO ! Noone is suggesting this - it doesn't work. str goes out of
scope when you exit foo and the buffer returned is therefore invalid.
const char* foo ()
{
std::string* str = new string ("Hello");
return str->c_str();

}

This is also wrong but for a different reason - the memory will not be
freed (there is no "might" about it) so although you can use the
returned const char* safely, you now have a memory leak because you
have no way of destroying the newed string.

You have to get what's happening with local and heap-based objects
clear in your head to be able to use C++ properly.
 

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

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top