malloc on struct containing unique_ptr - c++

Let's say I have the following structure:
struct MyStruct {
int myInt;
std::unique_ptr<Something> myUniquePtr;
}
What's wrong when malloc() is used to allocate memory (compared to using new I understand the unique_ptr constructor is not called). What does happen to myUniquePtr?
Let's say just after malloc I perform:
myUniquePtr = std::make_unique<Something>(...)
Is myUniquePtr a valid object?
What could be the consequences?

unique_ptr is a class type. malloc() only allocates raw memory, it does not call any class constructors within that memory. Thus, myUniquePtr will not be initialized correctly, and so cannot be used for anything meaningful since it is not a valid object. It can't be read from. It can't be assigned to. Nothing.
If you use malloc() (or any other non-C++ allocator) to allocate memory for an object, you must use placement-new afterwards to ensure the object is actually initialized properly in that memory before you can then use the object, eg:
void *memory = malloc(sizeof(MyStruct));
MyStruct *pMyStruct = new(memory) MyStruct;
...
pMyStruct->~MyStruct();
free(memory);

Related

How to manually initialize std::list 's objects in C++? What to do if a pointer of class has a member list<>, can not use new?

Suppose this is a struct/class in c++
struct MyClass{
list<int> ls;
};
Now maybe due to some reason, it is not possible to initialize pointer of 'MyClass', and the memory is being allocated manually
MyClass *pointer = calloc(1, sizeof(MyClass));
pointer->ls.push_back(123); // <----- this line causes core dump
Although it works fine with pure C++ method like this:-
MyClass *pointer = new MyClass;
pointer->ls.push_back(123);// All good, no problem
So is there any function available in std::list to resolve this issue?
I tried doing the same with std::vector, by there was no problem in that when I used calloc()
struct MyClass{
vector<int> ls;
};
MyClass *pointer = calloc(1, sizeof(MyClass));//using calloc
pointer->ls.push_back(123); // All Good
But on doing this using malloc:-
struct MyClass{
vector<int> ls;
};
MyClass *pointer = malloc(1, sizeof(MyClass));//using malloc
pointer->ls.push_back(123); // Core dump :-(
C++ differentiates between memory and objects in that memory. You are allocating memory with malloc or calloc, but you are not creating any object in the memory you allocated.
You can manually create an object in allocated storage using the placement-new expression:
new(pointer) MyClass /*initializer*/;
This creates a new MyClass object at the storage location that pointer points to. /*initializer*/ is the optional initializer for the object and has the same meaning as in a variable declaration
MyClass my_class /*initializer*/;
You may need to #include<new> to use the placement-new form I used above and you need to make sure that the allocated memory block is large enough and sufficiently aligned for the MyClass object type.
Using a pointer as if it points to an object even though none was created at the storage location causes undefined behavior, which you are observing. Note that this is true for any (even fundamental) types technically. Probably that will change in the future to allow at least trivial types (or some similar category) to be created implicitly when used, but for non-trivial class types such as the standard containers, this certainly will not change.
Also note that malloc and calloc return void*, which in C++ cannot be implicitly cast to a different pointer type. You need to cast it explicitly:
MyClass *pointer = static_cast<MyClass*>(malloc(sizeof(MyClass)));
or rather than doing that, save the pointer as void* without any cast to hint at you that it is not actually pointing to an object, but just memory.
You can still pass that void* pointer to the placement-new and the placement-new will actually return you a pointer of the correct type pointing to the new object (there are some specific cases where you are actually required to use this pointer):
void *mem_ptr = malloc(sizeof(MyClass));
auto obj_ptr = new(mem_ptr) MyClass /*initializer*/;
You should also avoid using malloc and calloc and the like. C++ has its own memory allocation function, called (confusingly) operator new. It is used like malloc (initializing the memory to zero like calloc does is not useful, because the initializer in the placement-new can and/or will do that):
void* pointer = operator new(sizeof(MyClass));
and its free analogue is:
operator delete(pointer);
It still only allocates memory and does not create object as the placement new does.
The non-placement new expression new MyClass; allocates memory (by call to operator new) and creates an object as if by the placement-new form mentioned above.
You do not need to bother with all of this though, because you can just use a smart pointer and initialize it later, if you need that:
std::unique_ptr<MyClass> ptr; // No memory allocated or object created
ptr = std::make_unique<MyClass>(/*constructor arguments*/); // Allocates memory and creates object
// Object is automatically destroyed and memory freed once no `std::unique_ptr` references the object anymore.
You should not use raw pointers returned from new, malloc or the like as owning pointers in the first place. std::unique_ptr has the correct ownership semantics by default and requires no further actions by you.

Initialise std::string in uninitialised, unowned memory

I'm using a C library (libwebsockets) which allows some user-data for each client. The library owns this memory, passes it as a void*, and my code reinterpret_cast's it to my user-data type.
I'm trying to add a std::string field to this class and am now seeing segfaults. Calling functions on this class causes errors, which is fair enough as it's likely backed by uninitialised memory.
How can I initialise that memory> I've tried assigning (the assignment operator segfaults) and calling various functions such as clear. I'm guessing there's a C++ mechanism for this.
Furthermore, how can the destructor be called when the string is no longer needed?
Assuming that you have a type something like this:
class MyType
{
std::string foo;
std::string bar;
};
And assuming that the void * points to an uninitialized allocation of at least sizeof(MyType) bytes, then you can construct it (and all contained objects) using placement new syntax:
void init_callback(void * ptr) {
new (ptr) MyType();
}
Similarly, you can destruct your type (which will destruct all contained objects) by calling the destructor directly.
void destroy_callback(void * ptr) {
MyType * mine = reinterpret_cast<MyType *>(ptr);
mine->~MyType();
}
Generally you don't call destructors directly, but you have to because you can't safely delete the pointer. The rule "every new should have one delete" has an analog in this situation: "every placement-new should have one explicit call to the destructor."
You can use placement-new to create an object in the provided memory:
std::string * s = new(memory) std::string;
and call the destructor to destroy it before reusing or releasing the memory:
s->std::string::~string();
If you find that a bit of a mouthful, then using std::string; will reduce it to s->~string();

Does memory get allocated in C++ when assigning to a dynamic array?

Suppose in C++, I have the following code:
class Foo {
private:
double* myData;
public:
Foo(double data[]) {
myData = data;
}
}
int main() {
double mainData[] = {1.0};
Foo myfoo(mainData);
}
As far as my knowledge can tell, mainData is treated as a pointer when passed into the Foo constructor, so the line myData = data only assigns the pointer address. So no extra memory is allocated here, right? But then, is the Foo class responsible for providing a destructor that deallocates myData's memory? Or do we have a dynamic array pointer that actually points to stack memory?
Also, if I want to protect Foo's myData from changing when mainData is changed, is there a simple way to force the Foo constructor to copy it? Ideally myData would be a simple array, not a pointer, but changing the line double* myData to double myData[] doesn't seem to work because the size of the array is unknown until runtime.
The parameter here is not a dynamic array:
Foo(double data[])
In fact the declaration is equivalent to this:
Foo(double * data)
Even decltype will tell you they are the same thing, and those two signatures will conflict as overloads.
So, there is no allocation. You are only passing a pointer to the first element of the array.
Also, the only place where C++ will automatically copy an array is when it is a member of a class, and the empty bracket [] syntax for indeterminate size is not allowed for members. (Or if it is, the size is already determined by the time the class type is complete, before the copy constructor or assignment operator is generated.)
Also, if I want to protect Foo's myData from changing when mainData is changed, is there a simple way to force the Foo constructor to copy it? Ideally myData would be a simple array, not a pointer, but changing the line double* myData to double myData[] doesn't seem to work because the size of the array is unknown until runtime.
You can keep a copy of the data, but you will need a pointer if its size (or at least an upper bound) is unknown at compile time. I would recommend std::vector over a naked pointer, or at least std::unique_ptr< double[] >.
In this case myData points to an address on the stack, which calls the destructor for Foo when the function goes out of scope. Generally arrays are described as being dynamic when you use the keyword new to allocated them.
As for your second question, you're probably going to have to pass into the constructor a pointer to the array and the length of the array. You then need to dynamically create a double array (pointed to by myData), using the length that was passed in, and then make a copy.
Don't forget to delete the memory in the destructor.
A pointer only holds a memory address, without new or delete involved a pointer has nothing to do with allocation or deallocation. Thus your code wont invoke any memory allocation.
In order to delete an (dynamically allocated) array you have to do delete[] foo;
Only dynamically allocated objects must be deleted, if you class takes ownership (it manages the array, calls delete on destruction) passing an array with automatic storage duration is a very bad idea.
Yes, it does not allocate additional memory.
No, the destructor won't do anything with the class field if it hadn't been told so.
in Foo class instances will have pointer to data that is allocated/managed by other classes this is very bad design. The best thing is to make the Foo constructor make a copy and store it in the pointer. Then in the desctructor free that one. This would require passing the length of the array to the Foo constructor. I hope that helps.

One class with a vector data member

I would like to define a class with a vector data member. The class looks as follows
class A{
...
private:
std::vector<int> v1;
...
};
If I use operator new to allocate memory for class A, the program is OK. However, if I get the memory from the pre-allocated memory and cast the pointer to type A*, the program will crash.
A* a = new A;
A* b = (A*)pre_allocated_memory_pointer.
I need one vector with variable size and hope to get the memory for A from one pre-allocated memory. Do you have any idea about the problem?
An std::vector is an object that requires initialization, you cannot just allocate memory and pretend you've got a vector.
If you need to control where to get the memory from the solution is defining operator::new for your class.
struct MyClass {
std::vector<int> x;
... other stuff ...
void *operator new(size_t sz) {
... get somewhere sz bytes and return a pointer to them ...
}
void operator delete(void *p) {
... the memory is now free ...
}
};
Another option is instead to specify where to allocate the object using placement new:
struct MyClass {
std::vector<int> x;
... other stuff ...
};
void foo() {
void * p = ... get enough memory for sizeof(MyClass) ...
MyClass *mcp = new (p) MyClass();
... later ...
mcp->~MyClass(); // Call destructor
... the memory now can be reused ...
}
Note however that std::vector manages itself the memory for the contained elements and therefore you'll need to use stl "allocators" if you want to control where the memory it needs is coming from.
It is not enough to cast the pre-allocated memory poiner to your user-defined type unless this UDT is "trivial".
Instead, you may want to use the placement new expression to actually call the constructor of your type at the provided region of memory:
A* b = new(pre_allocated_memory_pointer) A();
Of course, you need to ensure that your memory is properly aligned and can fit the whole object (i.e. its size is >= sizeof(A) ) beforehand.
Don't also forget to explicitly call the destructor for this object before de-allocating the underlying memory.
b.~A();
deallocate(pre_allocated_memory_pointer);
As I understand your question you are confusing the data memory of the std::vector with the memory it takes up as a member.
If you convert pre_allocated_memory_pointer to A*, then no constructor got called and you have an invalid object there. This means that the v1 member will not have been constructed and hence no memory has been allocated for the vector.
You could use placement new to construct the A instance at the pre_allocated_memory_pointer position but I doubt that is what you want.
In my opinion you want a custom allocator for the vector that gets the memory for the vector's data from the preallocated memory pool.

how do you delete an object allocated with placement new

there are quite a few faces for the new operator in c++, but I'm interested in placement new.
Suppose you allocate memory at a specific memory location
int memoryPool[poolSize*sizeof(int)];
int* p = new (mem) int; //allocates memory inside the memoryPool buffer
delete p; //segmentation fault
How can I correctly deallocate memory in this case?
What if instead of built-in type int I would use some class called myClass?
myClass memoryPool[poolSize*sizeof(myClass )];
myClass * p = new (mem) myClass ; //allocates memory inside the memoryPool buffer
delete p; //segmentation fault
Thanks for your help.
In the first case, there's no point in using placement new, since int doesn't have a constructor.
In the second case, it's either pointless (if myClass is trivial) or wrong, since there are already objects in the array.
You use placement new to initialise an object in a block of memory, which must be suitably aligned, and mustn't already contain a (non-trivial) object.
char memory[enough_bytes]; // WARNING: may not be properly aligned.
myClass * c = new (memory) myClass;
Once you've finished with it, you need to destroy the object by calling its destructor:
c->~myClass();
This separates the object's lifetime from that of its memory. You might also have to release the memory at some point, depending on how you allocated it; in this case, it's an automatic array, so it's automatically released when it goes out of scope.
In your case there is no need to deallocate it, your int array will be deallocated once you return from your function. You should only call explicitly your destructor:
p->~myclass();
to keep you buffer correctly aligned use std::aligned_storage, look in here for example:
http://www.cplusplus.com/reference/type_traits/aligned_storage/