In this Informit C++ guide, I read this:
Using malloc() to create a non–POD object causes undefined behavior:
//disastrous!
std::string *pstr =(std::string*)malloc(sizeof(std::string));
I didn't understand 2 points here :
Pointers are PODs. Then why it is called non-POD here? (Maybe I have to understand POD better.)
How can this be so disastrous? (I guess I have to understand string Internals for this.)
Please explain!
pointers are PODs then why here it is called non-POD
It's not talking about the pointer, but the std::string.
It's disastruous because malloc doesn't call the constructor, so you'll have pstr a std::string pointer that points to a std::string that wasn't properly constructed. The memory was allocated but it wasn't initialized properly, because of the missing constructor call.
The correct way is
std::string *pstr = new std::string;
The clean way is to just have a variable in automatic storage:
std::string str;
Here you are allocating a standard string, not allocating a pointer to a standard string. Note that you are passing sizeof(std::string) to malloc; that is how much memory you are getting back...note the size of the object is bigger than the size of a pointer. If you were only allocating a pointer, you'd expect the size passed in to be sizeof(std::string*).
The pointer you receive back is how you keep track of the result of the allocation, but that pointer isn't living on the heap. Here it's just being stored in an ordinary variable. Had you allocated a pointer instead, then your variable to keep track of it would need to be a pointer-to-a-pointer.
Anyway, if you wanted to, you could legally allocate a pointer to a standard string like this:
std::string str;
std::string** ptr_to_pstr = (std::string**)malloc(sizeof(std::string*);
*ptr_to_pstr = &str;
Why you would want to is not entirely clear. But neither is it clear why you'd use malloc in C++. :)
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.
When I create a class, include a pointer in it, and create an object in automatic storage, should I include a destructor in the class? (is it necessary to free the space in the memory?)
Example:
class Node{
char *Name;
int age;
Node(char *n = 0, int a = 0) {
name = strdup(n);
age = a;
}
~Node(){
if (name != 0)
delete(name);
}
}
Node node1("Roger",20);
is it necessary to free the space in the memory?
Yes, it's essential to avoid memory leaks.
Anyway you must use free(name); in your example, since strdup() is a pure C function, and uses the malloc() function to allocate the memory for the copy returned.
Also, you should avoid managing raw pointers yourself in C++. Either use smart pointers, or standard C++ containers, or for your specific case simply std::string.
Raw pointers don't go well with, respectively complicate, implementing the Rule of Three (5/zero).
If you have something allocated from a C-style interface, you can always use a smart pointer, and provide a custom deleter function, that actually uses the appropriate free() call.
If your class has a pointer that points to memory that is allocated with new \ new[] \ malloc() then you need to implement the Rule of Three
That said, instead of using a raw char * and manual memory management, use a std::string instead. you can still get a const char* out of it if you need it for other functions but it fully self managed container. With it you would not need to provide a copy constructor or destructor as the default ones provided by the compiler will work.
Yes, this is mandatory to avoid memory leaks. It doesn't matter if you are using a class or something else. It's important what strdup says. But you must not use delete, instead use free. The memory in strdup is created by using malloc, not new.
http://pubs.opengroup.org/onlinepubs/009695399/functions/strdup.html
strdup - duplicate a string
The returned pointer can be passed to free(). A null pointer is
returned if the new string cannot be created.
P.S. Don't miss const in your declaration of char *n, otherwise the caller might expect the string is modified and a simple-string literal cannot be passed without a warning.
P.S.2: Prefer using nullptr instead of 0. This has been discussed several times on SO.
class Tool
{
public:
Tool();
~Tool();
private:
char **s;
};
char *s1[]={"hello","world"};
How can I initialize s and make it same as s1?
s={"hello","world"}
doesn't seem to work.
While you could use a std::vector<std::string>, I feel it's more beneficial to you to directly answer your question.
char** s is a pointer to a pointer; possibly a pointer to the first pointer in an array of pointers.
char* s1[] is an array of pointers to const data (and should have actually been made const).
If you want s to work similarly to s1, you first need to allocate the array of pointers, which is the reason std::vector was recommended by others. You could do it yourself with new, but you have to release the allocated memory at some point. Using new directly is prone to leaks. std::vector will release its allocated memory when the object is destructed. You too could call delete[] in your destructor if you wanted to.
When your array has been allocated, you then need to std::copy the array of pointers in s1 to the array of pointers in s. It's not a single assign operation.
Given a function foo with a statement in it:
void foo() {
std::string * s;
}
Is memory reclaimed after this function returns?
I am assuming yes because this pointer isn't pointing to anything but some people are saying no - that it is a dangling pointer.
std::string* s is just an uninitialized pointer to a string. The pointer will be destroyed when function foo returns (because the pointer itself is a local variable allocated on the stack). No std::string was ever created, hence you won't have any memory leak.
If you say
void foo() {
std::string * s = new std::string;
}
Then you will have memory leak
This code is typical when people learn about strings a-la C, and then start using C++ through C idioms.
C++ classes (in particular standard library classes) treat objects as values, and manage themselves the memory they need.
std::string, in this sense is not different from an int. If you need a "text container", just declare an std::string (not std::string*) and initialize it accordingly (uninitialized std::strings are empty by definition - and default constructor) than use it to form expression using method, operators and related functions like you will do with other simple types.
std::string* itself is a symptom of a bad designed environment.
Explicit dynamic memory in C++ is typically used in two situation:
You don't know at compile time the size of an object (typical with unknown size arrays, like C strings are)
You don't know at compile time the runtime-type of an object (since its class will be decided on execution, based on some other input)
Now, std:string manage itself the first point, and does not support the second (it has no virtual methods), so allocating it dynamically adds no value: it just adds all the complication to manage yourself the memory to contain the string object that is itself a manager of other memory to contain its actual text.
This code just creates a pointer to somewhere in memory, which contains string value and it points to somewhere which has been allocated before and it does not allocate new string.
it just allocate a memory for pointer value and after function return it's no more valid...
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.