I have this simple function:
const wchar_t *StringManager::GetWCharTStar(int stringId)
{
std::wstring originalString = StringManager::GetString(stringId);
const wchar_t *retStr = originalString.c_str();
return retStr;
}
At the second line of that function, I have the correct wchar_t*. However, when I go to return, the data switches to garbage data. There are no functions in between. What gives?!
originalString is allocated on the stack. The .c_str() method just returns a pointer to some contiguous internal memory of the wstring object. When the function returns, originalString goes out of scope and is destroyed, therefore the pointer value you return points to deleted memory.
If you need to do this, you should make a copy of the data into memory you allocate with new or malloc(), and then the caller must delete/free() that memory.
You are returning a pointer to a temporary. When originalString goes out of scope, the data your pointer is pointing to is going to be deleted.
std::wstring originalString; is a local variable inside the body of your GetWCharTStar function.
As soon as you leave the scope of the GetWCharTStar() function, this local variable gets destroyed and the pointer you return is no more valid.
The following code might eventually work:
const wchar_t *StringManager::GetWCharTStar(int stringId)
{
const std::wstring& originalString = StringManager::GetString(stringId);
const wchar_t *retStr = originalString.c_str();
return retStr;
}
Provided StringManager::GetString() returns a reference:
const std::wstring& StringManager::GetString(int stringId);
However, this is still risky as it assumes the strings managed by your StringManager class will never be relocated in memory. For example, if StringManager is implemented with the help of an std::vector then as soon as the vector needs to expand, its previous content gets copied elsewhere in a larger memory block and you end up holding a reference to an object that is no more there.
In other words, avoid returning handles to internal data.
The previous answers are mostly correct, except for one little detail. You're not returning a pointer to a destroyed object, you're returning a pointer owned by a destroyed object. When that object was destroyed, the object your pointer was pointing at was destroyed as well.
This is a FAQ. You are returning a pointer to an object that is freed (originalString object) before you actually get to use it.
Related
As far as i know, std::string creates a ident array-copy of its content when you call the c_str()/data() methods (with/out terminating NUL-char, does not matter here). Anyway, does the object also take care of freeing this array or do I have to?
In short:
std::string hello("content");
const char* Ptr = hello.c_str();
// use it....
delete[] Ptr; //// really ???
I just want to be on the safe side when it comes to memory allocation.
No you don't need to deallocate the ptr pointer.
ptr points to a non modifyable string located somewhere to an internal location(actually this is implementation detail of the compilers).
Reference:
C++ documentation:
const char* c_str ( ) const;
Get C string equivalent
Generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters.
A terminating null character is automatically appended.
The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.
std::string handles this pointer so don't release it. Moreover, there are two limitations on using this pointer:
1. Don't modify string that is pointed by this pointer, it is read-only.
2. This pointer may become invalid after calling other std::string methods.
No need, the dtor of the string class will handle the destruction of the string so when 'hello' goes out of scope it is freed.
Not only you don't need to free the pointer but you in fact should not. Otherwise the destructor of std::string will attempt to free it again which may result in various errors depending on the platform.
The std::string class is responsible for freeing the memory allocated to contain the characters of the string when an object of the class is destructed. So if you do
delete[] Ptr;
before or after hello object is destructed (leaves the C++ {} scope it was created in), your program will run into a problem of trying to free a memory block that is already freed.
A std::string is allocated on the stack (automatic storage duration) and assigned to a pointer. Then the pointer will be set to null.
std::string* myString = &std::string("");
myString = nullptr;
Is myString immediately deallocated after the second instruction or only after the function returns respectively if it's a member after the object is destroyed.
You cannot assign a string to a pointer. You can however assign the adress of a string to a string pointer. Let me change your code to valid C++:
std::string s = "";
std::string* s_ptr = &s;
s_ptr = nullptr;
The fact that you you change the value of a pointer that happens to point to s does not affect the string at all. Imagine you write the adress of a friends house on a piece of paper. Does the house get destroyed when you erase the adress on that piece of paper? Fortunately not.
PS: Well, the limit of this analogy is that in C++ you can use "the piece of paper" and say "destroy the house at this adress" (aka delete s_ptr, which would be super wrong in that case, as the string the pointer is pointing to was not created via new). Fortunately this does not work in real life ;)
myString itself does not get "deallocated" anywhere, because it was never allocated. myString was instantiated in automatic scope.
When the scope where myString was declared terminates, myString goes out of scope and gets destroyed. If myString was declared in the function's top scope, this happens when the function returns. Until its scope terminates, myString itself remains a valid instance of a pointer.
The first statement sets myString to point to a temporary object that gets immediately destroyed. The statement by itself is valid, but dereferencing the pointer from that point on will result in undefined behavior. The very next statement sets the pointer to nullptr, so no undefined behavior occurs.
I have a function that takes a (char* const*). The data I am provided is in a std::string. So I'm doing this:
void blahblah(std::string str)
{
const char * cc = str.c_str();
ConstCharFunction(&cc);
}
This works well. My question is do I need to clean-up the memory used by the const char ala:
delete cc;
Or is cc just a pointer to a mem location in std:string...
It's a pointer to memory allocated in std::string. When the std::string falls out of scope, the memory is released. Be sure not to hold onto the pointer after that!
No you don't need to delete cc. It is indeed a pointer held by the std::string object.
See here
A program shall not alter any of the characters in this sequence.
The pointer returned points to the internal array currently used by the string object to store the characters that conform its value.
Just be careful as the pointer returned by c_str() may be invalidated by calling modifying methods of the string.
This is from a small library that I found online:
const char* GetHandStateBrief(const PostFlopState* state)
{
static std::ostringstream out;
// ... rest of the function ...
return out.str().c_str()
}
In my code I am doing this:
const char *d = GetHandStateBrief(&post);
std::cout<< d << std::endl;
Now, at first d contained garbage. I then realized that the C string I am getting from the function is destroyed when the function returns because std::ostringstream is allocated on the stack. So I added:
return strdup( out.str().c_str());
And now I can get the text I need from the function.
I have two questions:
Am I understanding this correctly?
I later noticed that out (of type std::ostringstream) was allocated with static storage. Doesn't that mean that the object is supposed to stay in memory until the program terminates? And if so, then why can't the string be accessed?
strdup allocates a copy of the string on the heap, which you have to free manually later (with free() I think). If you have the option, it would be much better to return std::string.
The static storage of out doesn't help, because .str() returns a temporary std::string, which is destroyed when the function exits.
You're right that out is a static variable allocated on the data segment. But out.str() is a temporary allocated on the stack. So when you do return out.str().c_str() you're returning a pointer to a stack temporary's internal data. Note that even if a string is not a stack variable, c_str is "only granted to remain unchanged until the next call to a non-constant member function of the string object."
I think you've hit on a reasonable workaround, assuming you can't just return a string.
strdup() returns a char* pointer that is pointing to memory on the heap. You need to free() it when you're done with it, but yes, that will work.
The static local variable std::ostringstream out makes no sense in this case, unless the std::string being returned was also static which your observation is showing to be not true.
In GetHandStateBrief, variable out does not need to be static. You need an explicit static string to replace the temporary that was being created in your original call to out.str():
static std::string outStr;
std::ostringstream out;
... rest of function ...
outStr = out.str();
return outStr.c_str();
The function below tests if the input string contains a double.
bool is_double(const std::string& str)
{
char* p;
strtod(str.c_str(), &p);
return *p == 0;
}
What happens to pointer p after the function returns?
You have two variables to consider: str and p.
The string str is passed as a const reference, so it's lifetime must be managed outside the scope of this function, so it cannot be leaked by this function.
With the character pointer p, we can consider the pointer itself and what it points to. According to the documentation, it is set to "...point to the first character after the number." Meaning, it points to memory inside the string you've passed; it does not get set to newly allocated memory. Since you're already managing the lifetime of str properly, and nothing new has been allocated, you don't have to free what it points to. The pointer variable itself is created on the stack, so its lifetime is that of the function.
So, no, you're not leaking.
A resource leak happens when you allocate a resource that becomes unreachable outside a certain scope and you didn't free it nor can get back a reference to it, whether that resource is dynamic memory, mutexes, or any other process-bound resource.
In your case, you're creating some variables and using a function that doesn't do any dynamic memory allocation so all of your stuff are in the stack => no memory leak because it's "freed" once you return from the function.
As the pointer is within the scope of your function and not declared as anything global, I believe it will be automatically erased after the execution of the function.
pointer p will is set by the function to the next character in str after the numerical value.
so it won't leak memory
also you can use
bool is_double(const std::string& str)
{
double d;
d = strtod(str.c_str(), NULL);
return d != 0.0;
}