I have such class:
class Kot{
public:
string name;
};
I create an instance of it:
Kot* kot = new Kot;
kot->name = "John";
Then I want to create a duplicate of string:
string name;
name = strdup(kot->name.c_str());
I use strdup because I want to delete kot and use only name variable.
But I have a 5 bytes memory leak due tonamememory allocation.
How can I free it safely? I tried to dodelete &name`, but I have:
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
You probably detected a 5-byte memory leak, but it is not because of the string.
Each call to strdup creates a new char[] of the size matching the length of the string. You should bind it to a raw pointer char* and remove it at some point.
What you did instead, is that you create a temporary char* pointer. Let's call it temp for our purposes.
The temp string is then passed to std::string's constructor. The std::string makes another copy of it, leaving the original temp intact.
Then the temp pointer just dissapears, without properly clearing the memory.
At the end, when the std::string object is destroyed, it properly clears its own, private copy of the string. But the memory previously pointed by temp is never freed.
A quick fix would be to:
char* temp = strdup(kot->name.c_str());
name = temp;
free(temp);
However, you don't even have to do that! If you assign one std::string object to another, you make a proper copy of its contents already. So:
name = kot->name;
will most likely do exactly what you are trying to achieve already -- making a copy of kot->name within your name. In such scenario, name and kot->name become two completely separate strings with the same (copied) content. From that point onward, changing/deleting one does not affect the other.
You use free(), not delete.
Per the standard documentation:
The strdup() function shall return a pointer to a new string, which is
a duplicate of the string pointed to by s. The returned pointer can be
passed to free(). A null pointer is returned if the new string
cannot be created.
You have a memory leak here:
name = strdup(kot->name.c_str());
because you never release memory allocated by strdup.
To avoid this problem you can simply construct name from the kot->name:
name = kot->name;
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.
Recent times I am confused with the use of new keyword with the string data type. Can you please try to clarify it
What's the difference between the following string initialization:
1)
string* name = new string("abc") ;
....
delete name;
2)
string name = "abc";
Is it advisable to use new keyword , as the values within string is any how stored in heap as internal buffers of std::string. It will be good if anyone explains it with storage location.
What's the difference between returning the string vs string*
string* name()
{
string* name = new string("abc") ;
return name;
}
string name()
{
string name = "abc";
return name;
}
There are several reasons to prefer the second approach over the first:
Most important reason: a string is a string, period. A string* may point to a string, or it may be NULL/nullptr, or it may point to a random location in memory. Therefore, you should use plain old string's over string*'s wherever possible as using them is less prone to errors.
Declaring a string object places it on the stack, meaning that it will automatically cleaned up when it leaves scope. Using new means that you now have to manually clean up your allocated memory.
new is a relatively slow operation. Using stack variables is much faster.
While string store's its data on the heap, allocating the string itself on the heap still adds another level of indirection.
string is an actual string being created in the current scope, and it will be cleaned up automatically when the scope exits.
void function() {
{ // a scope
string test = "hi";
}
// test is destroyed here and cannot be used.
}
string* is a pointer to a string that isn't tied to the current scope. A pointer starts out as invalid (usually assigned nullptr by the user, which means it doesn't point to anything), and you need to assign a memory location to it; it would be an error to access it if it wasn't. When you use new and assign a value to the pointer, then you have a string that is located on the heap and not in the current scope, and you need to delete it manually, otherwise the memory is leaked. You can wrap a pointer in a smart pointer to have it delete itself automatically.
void function() {
{
string *test = new string("hi");
}
// test is *not* destroyed and memory was leaked
}
void function() {
unique_ptr<string> test;
{
test = unique_ptr<string>( new string("hi") );
}
} // test is deleted when the function exits and the unique_ptr goes out of scope.
The main reason to avoid allocating objects with new is that it is slower than using items located on the stack, and the main reason to use new is that it may be faster to pass around a pointer to an object rather than copying the object.
However, while copying a string may be slow, you can also move a string, which makes it fast.
Moving a string simply relocates the internal buffers of string A into string B
string function() {
string test = "abcdefg";
return test; // when test is returned, it is moved to the calling function.
}
You can also move a string explicitly.
string A = "hello";
string B( std::move(A) );
// A is invalid, and B contains "hello"
Usually std::strings are not created with new by themselves, but rather a struct or class they reside in may be.
An example using pointers, I may have a special class that I pass around to different functions:
class MyClass {
string a;
public:
const string *function1() { return &a; }
const string &function2() { return a; }
string function3() { return a; }
}
MyClass::function1 gives me a const pointer to the string, meaning no data is copied, and I can only read the string's value.
MyClass::function2 basically does the same thing as function1, but it uses a reference instead, references are like pointers but they must always contain a valid target. References are usually used in C++ over pointers.
MyClass::function3 returns a copy of the string, which an outside function can modify and it won't affect the one inside the class.
If we are using the new operator, the object will be created in heap memory and the reference pointer will be in stack. In your example,
string* name()
{
string* name = new string("abc") ;
return name;
}
name is a pointer variable which is stored in stack, that contains the address of string object. The actual object is stored in the heap. So it wont be destroyed after the method execution. The calling method will get the address of the object and we can refer it using that. We need to deallocate the string object memory using the 'delete' keyword.
Ex:
delete name;
If we are defining a string without new operator, it will be created in the stack itself and it will be automatically destroyed when the method execution gets over. Consider the example,
string name()
{
string name = "abc";
return name;
}
Here one object will be created in the stack frame of method name, after the method execution over, it will get destroyed.
The statement that uses the above function will be like
string a = name();
Here the operator=() method for the string class will be invoked and a new object will be created in the calling function's stack frame.
Hope this will help
I am initializing a char pointer with some random values, and when I am trying to delete it, I am unable to. Why is that?
Here is what I am doing:
int main()
{
char *s = new char[50]; /*
* I know there is no reason for
* using new if initializing, but
* in order to use delete we need
* to allocate using new.
*/
s = "Harry";
delete s;
return 0;
}
If you really want to practice with pointer, you need to fix your code. The main problem is you are trying to assign string literal( which is const char[6] in here) to pointer s then try to modify it by calling delete which invoke undefined behavior(UB).
char *s = new char[50];
strcpy(s, "Harry"); // don't assign string literal to it
// re-assign pointer to string literal,
// lost pre-allocated memory position and caused delete to fail
// it's UB to modify string literal
delete []s; // new[]/delete[], new/delete need to be called in pair.
Just use std::string instead.
#include <string>
std::string s("Harry"); // no worries
The problem is that after this assignment:
s = "Harry";
Then your s is no longer pointing to the memory you have allocated. It is pointing to a different array, or a const char[6] to be precise. The other array isn't dynamically allocated, and isn't on the heap. You can't delete variables that aren't on the heap.
In addition, by changing the s pointer to point at something else before the dynamically allocated memory has been freed, you introduce a memory leak.
To fix your code, either copy "Harry" into the s array by using strcpy, or use std::string instead.
You should never initialize a pointer with a string constant this way. It creates memory leaks which can be very dangerous.
When you allocated the memory using new, a 50 char memory was allocated in heap and its pointer is returned in s. when you were trying to initializing this value (wrong way) using s="Harry" , a new space is allocated in stack, initialized with this value and returned in s.
This memory allocated in stack cannot be deleted using delete call because it works only on heap.
Also, the memory initially allocated using new can no longer be accessed using s. Thus, you have a memory leak over here.
You can notice a different address in your pointer s after this wrong initialization by making small changes in your program:
#include <stdio.h>
int main()
{
char *s = new char[50];
printf("\n %u",s); // print address before init
s = "Harry";
printf("\n %u",s); // print address after init
// delete s; // cannot delete from stack
return 0;
}
Like others have already suggested, an array of character should be initialized using
strcpy(s, "Harry");
A char* is not actually a string. It is a pointer to some character with more characters to follow and ending with '\0'.
A character literal in C (and thus in C++) like "abc" is just an array of characters, with the compiler silently adding a '\0'. When you assign an array to a pointer, the array silently converts a pointer to the first element.
s = "Harry" means, the pointer s is assigned the address of the first character in the string literal "Harry". So the old value is lost and as this was the address of a dynamically allocated character array, leakage is supposed to happen.
std::strcpy, on the other hand, copies a string character by character from one array to another array. No pointers will be changed, only pieces of memory are copied. The pointer to the target array still points to the target array afterwards, only the data in that array has changed.
I don't think this occurs with initialized pointers.
When using a pointer, you can only delete (free) the memory it's pointing to, not the pointer itself, since it's an automatic object and will be deleted at the end of the block.
My code converts C++ strings to C strings somewhat often, and I am wondering if the original string is allocated on the stack. Will the C string be allocated on the stack as well? For instance:
string s = "Hello, World!";
char* s2 = s.c_str();
Will s2 be allocated on the stack, or in the heap? In other words, will I need to delete s2?
Conversely, if I have this code:
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
Will s2 now be on the heap, as its origin was on the heap?
To clarify, when I ask if s2 is on the heap, I know that the pointer is on the stack. I'm asking if what it points to will be on the heap or the stack.
string s = "Hello world";
char* s2 = s.c_str();
Will s2 be allocated on the stack, or in the heap? In other words... Will I need to delete s2?
No, don't delete s2!
s2 is on the stack if the above code is inside a function; if the code's at global or namespace scope then s2 will be in some statically-allocated dynamically-initialised data segment. Either way, it is a pointer to a character (which in this case happens to be the first 'H' character in the null-terminated string_ representation of the text content of s). That text itself is wherever the s object felt like constructing that representation. Implementations are allowed to do that however they like, but the crucial implementation choice for std::string is whether it provides a "short-string optimisation" that allows very short strings to be embedded directly in the s object and whether "Hello world" is short enough to benefit from that optimisation:
if so, then s2 would point to memory inside s, which will be stack- or statically-allocated as explained for s2 above
otherwise, inside s there would be a pointer to dynamically allocated (free-store / heap) memory wherein the "Hello world\0" content whose address is returned by .c_str() would appear, and s2 would be a copy of that pointer value.
Note that c_str() is const, so for your code to compile you need to change to const char* s2 = ....
You must notdelete s2. The data to which s2 points is still owned and managed by the s object, will be invalidated by any call to non-const methods of s or by s going out of scope.
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
Will s2 now be on the heap, as its origin was on the heap?
This code doesn't compile, as s is not a pointer and a string doesn't have a constructor like string(std::string*). You could change it to either:
string* s = new string("Hello, mr. heap...");
...or...
string s = *new string("Hello, mr. heap...");
The latter creates a memory leak and serves no useful purpose, so let's assume the former. Then:
char* s2 = s.c_str();
...needs to become...
const char* s2 = s->c_str();
Will s2 now be on the heap, as its origin was on the heap?
Yes. In all the scenarios, specifically if s itself is on the heap, then:
even if there's a short string optimisation buffer inside s to which c_str() yields a pointer, it must be on the heap, otherwise
if s uses a pointer to further memory to store the text, that memory will also be allocated from the heap.
But again, even knowing for sure that s2 points to heap-allocated memory, your code does not need to deallocate that memory - it will be done automatically when s is deleted:
string* s = new string("Hello, mr. heap...");
const char* s2 = s->c_str();
// <...use s2 for something...>
delete s; // "destruct" s and deallocate the heap used for it...
Of course, it's usually better just to use string s("xyz"); unless you need a lifetime beyond the local scope, and a std::unique_ptr<std::string> or std::shared_ptr<std::string> otherwise.
c_str() returns a pointer to an internal buffer in the string object. You don't ever free()/delete it.
It is only valid as long as the string it points into is in scope. In addition, if you call a non-const method of the string object, it is no longer guaranteed to be valid.
See std::string::c_str
std::string::c_str() returns a const char*, not a char *. That's a pretty good indication that you don't need to free it. Memory is managed by the instance (see some details in this link, for example), so it's only valid while the string instance is valid.
Firstly, even your original string is not allocated on the stack, as you seem to believe. At least not entirely. If your string s is declared as a local variable, only the string object itself is "allocated on the stack". The controlled sequence of that string object is allocated somewhere else. You are not supposed to know where it is allocated, but in most cases it is allocated on the heap. I.e. the actual string "Hello world" stored by s in your first example is generally allocated on the heap, regardless of where you declare your s.
Secondly, about c_str().
In the original specification of C++ (C++98) c_str generally returned a pointer to an independent buffer allocated somewhere. Again, you are not supposed to know where it is allocated, but in general case it was supposed to be allocated on the heap. Most implementations of std::string made sure that their controlled sequence was always zero-terminated, so their c_str returned a direct pointer to the controlled sequence.
In the new specification of C++ (C++11) it is now required that c_str returns a direct pointer to the controlled sequence.
In other words, in general case the result of c_str will point to a heap-allocated memory even for local std::string objects. Your first example is not duifferent from your second example in that regard. However, in any case the memory pointed by c_str() is not owned by you. You are not supposed to deallocate it. You are not supposed to even know where it is allocated.
s2 will be valid as long as s remains in scope. It's a pointer to memory that s owns. See e.g. this MSDN documentation: "the string has a limited lifetime and is owned by the class string."
If you want to use std::string inside a function as a factory for string manipulation, and then return C-style strings, you must allocate heap storage for the return value. Get space using malloc or new, and then copy the contents of s.c_str().
Will s2 be allocated on the stack, or in the heap?
Could be in either. For example, if the std::string class does small string optimization, the data will reside on the stack if its size is below the SSO threshold, and on the heap otherwise. (And this is all assuming the std::string object itself is on the stack.)
Will I need to delete s2?
No, the character array object returned by c_str is owned by the string object.
Will s2 now be on the heap, as its origin was on the heap?
In this case the data will likely reside in the heap anyway, even when doing SSO. But there's rarely a reason to dynamically allocate a std::string object.
That depends. If I remember correctly, CString makes a copy of the input string, so no, you wouldn't need to have any special heap allocation routines.
Code Segment 1:
wchar_t *aString()
{
wchar_t *str = new wchar[5];
wcscpy(str, "asdf\0");
return str;
}
wchar_t *value1 = aString();
Code Segment 2
wstring wstr = L"a value";
wchar_t *value = wstr.c_str();
If value from code segment 2 is not deleted then an memory leak does not occur. However, if value1 from code segment 1 is not deleted there is a memory leak. The internal code to wstring::c_str looks the same to me.
An important rule: you must use delete on anything that was created by new, and you mustn't delete anything else.
wstr.c_str() returns a pointer to a buffer that's managed by the wstring object. It will be deallocated when the string is destroyed, after which the pointer will no longer be valid. Using delete on this is wrong. The pointer will also be invalidated if you modify the string.
aString() returns a pointer to a buffer that was created using new[], so you must delete it when you've finished with it (using delete[], to match new[]). This is error-prone, which is why it is better practice to use resource-managing classes (like string, wstring, containers and smart pointers) rather than passing around raw pointers and hoping they are treated correctly.
Because c_str() returns you a pointer to the internal representation of the wstring. The class keeps control of the data it contains.
Taken from the basic_string::c_str() documentation from MSDN:
The returned C-style string should not
be modified, as this could invalidate
the pointer to the string, or deleted,
as the string has a limited lifetime
and is owned by the class string.
I'm going to go out on a limb and say that a wstring is not a wchar_t, but instead a class that has an operator to return a wchar_t *, so in the destructor of wstring, it likely frees its own copy of the wchar_t * it returns.