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.
Related
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);
Could you please suggest practical scenario/example/use of dynamic memory allocation and vector of pointers?
If I google, I am getting many websites explaining the concepts of dynamic memory allocation and but not able to get practical scenarios where we can use dynamic memory allocation in C++?
Thanks.
Static allocation:
You know the requested memory size at compile time, so you can define an array like:
int buf[20]; // This is an array of 20 ints
Dynamic allocation:
You allocate the storage at runtime. For example the needed array size is an input to your progam:
int *buf = new int[n]; // where n is some runtime known number.
<some code...>
delete[] buf; // In this case you must release the memory when you don't need it anymore
For example an usecase of an array of pointers is polymorphism. You have a class Base, and you have Derived classes (ie Der1, Der2, Der3). You want to store many object from those derived classes in an array. But you can't since the array type tells you what can you store in them. So in this case you can store the pointers to the Der* objects in the array, as if it is a Base* object.
struct Base
{
virtual ~Base() {};
virtual void doSomething() = 0;
};
struct Der1 : Base
{
virtual void doSomething(); // define what Der1 does for this function
};
struct Der2 : Base
{
virtual void doSomething(); // define what Der2 does for this function
};
struct Der3 : Base
{
virtual void doSomething(); // define what Der3 does for this function
};
int main()
{
// You allocate memory for Base* types so this is an array of pointers
Base* some_array[3]; // It can be also dynamically allocated
// And now you can store Der* in this array as:
some_array[0] = new Der1();
some_array[1] = new Der2();
some_array[2] = new Der3();
// There we did dynamic allocation with new!!!
// Since our objects are not in the some_array array, but somewhere in the memory,
// and we store pointers to them in the array
// And you can do:
some_array[0]->doSomething();
some_array[1]->doSomething();
some_array[2]->doSomething();
// Release the DYNAMICALLY!! allocated things
delete some_array[0];
delete some_array[1];
delete some_array[2];
}
But there are many other usecases. This is just one of them...
Dynamic memory allocation: when you need to use arrays but don't know what size will be required and the compiler doesn't support run-time size on the array allocations. std::vector is useful.
Vector of pointers: when you need to sort an array of big objects, you shouldn't swap elements directly because some of them (like arrays) can not evade extra copies of POD elements. Swapping pointers is enough here and is faster to do against copying millions of elements.
std::vector<std::shared_ptr<float>> bigArrays;
... allocate ...
// sort elements(big objects/arrays) on their elements at index
std::sort(bigArrays.begin(),bigArrays.end(),
[]
(std::shared_ptr<float> e1, std::shared_ptr<float> e2)
{
return e1[index]<e2[index];
}
);
Sometimes you have an array of atomics:
// behold the false-sharing!
std::vector<std::atomic<int>> atomics;
atomics.push_back(std::atomic<int>());
not possible to dynamically build after the initialization. Their copy-constructors are deleted. Instead, use a vector of pointers:
std::vector<std::shared_ptr<std::atomic<int>>> atomicPtrs;
atomicPtrs.push_back(std::make_shared<std::atomic<int>>());
Sometimes the data pointed to belongs to another domain:
std::vector<float *> gpuMatrices(100);
for(int i=0;i<100;i++
cudaMalloc ( gpuMatrices.data()+i, 1024*1024*sizeof(float) );
so that you can't work with plain vectors anymore. Then storing those (e.g. cuda) buffer pointers in a vector lets you manage the resources.
Sometimes the vector has to support different derived classes of a base class:
std::vector<Dog,Cat,Horse,Elephant> animals;
it won't work. Need to have this:
std::vector<Iquackable*> animals(100);
animals[0]=(Iquackable*)getDuckPtr();
animals[0]->quack(); // "quack"
animals[1]=(Iquackable*)getCatPtr();
animals[1]->quack(); // "meow"
Sometimes your matrix is so huge that you need to have each row of it local to its own numa node in a computation:
my_1TB_matrix[0]=getDataPtr(x,0); // numa_alloc_local(..) from another thread
my_1TB_matrix[1]=getDataPtr(x,1); // numa_alloc_local(..) from another thread
...
so that a CPU (of a multi-CPU system) working on its own row will have better timings.
Sometimes all you have is a pointer because they include each other:
std::vector<Node *> sparseOctree(5);
octree[0]=getRootNodePtr();
octree[1]=octree[0]->createChildNode();
octree[2]=octree[0]->createChildNode();
octree[3]=octree[1]->createChildNode();
octree[4]=octree[1]->createChildNode();
..
Sometimes you need to roll your own memory pool to make things faster:
std::vector<Memory *> heap(500);
heap[0] = allocateMemory();
heap[1] = allocateMemory(); freeMemory(heap[1]);
heap[2] = allocateMemory();
heap[3] = allocateMemory();
defragmentation(heap);
without touching the data the memory holds.
Given the following code:
class MyClass
{
public:
char array[10];
};
int main()
{
MyClass *p = new MyClass;
...
}
As far as I understand - new allocates the object on the heap.
But also, the array is allocated on the stack (no new operator).
So, is the array allocated on heap (because the object is at the heap) or on the program stack?
But also, the array is allocated on the stack (no new operator)
No, the array is a member of the object. It's a part of it. If the object is dynamically allocated, then all of its parts are too.
Note I said all of its parts. We can tweak your example:
class MyClass
{
public:
char *p_array;
};
int main()
{
char array[10];
MyClass *p = new MyClass{array};
// Other code
}
Now the object contains a pointer. The pointer, being a member of the object, is dynamically allocated. But the address it holds, is to an object with automatic storage duration (the array).
Now, however, the array is no longer part of the object. That disassociation is what makes the layout you had in mind possible.
What MyClass *p = new MyClass; really means is that you want to allocate sizeof(MyClass) bytes on the heap/free store to store every member of MyClass. The size of a class is based on it's members. array is a member of MyClass and thus because MyClass is allocated on the free store, so is 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.
Hello So I'm experimenting with creating objects and arrays with preallocated memory. For instance I have this following code:
int * prealloc = (int*)malloc(sizeof(Test));
Test *arr = new(prealloc) Test();
Where test is defined as follows:
class Test {
public:
Test() {
printf("In Constructor\n");
}
~Test() {
printf("In Destructor\n");
}
int val;
};
In this scenario if I call delete it will actually release the memory which is bad, b/c maybe I'm using some type of memory manager so this will sure cause some problems. I searched in the internet and the only solution that I found was to call the destructor explicitly and then call free:
arr->~Test();
free(arr);
Is there another way to do this? is there perhaps a way to call delete and tell it to just call the destructor and not to release the memory?
My second problem was when working with arrays, like the previous example you can pass to new the pre-allocated memory:
int * prealloc2 = (int*)malloc(sizeof(Test) * 10);
Test *arr2 = new(prealloc2) Test[10];
If I call delete[] it will not only call the destructor for each element in the array but it will also release the memory which is something I don't want. The only way I have found that it should be done is to go through the array and call the destructor explicitly, and then call free. Like with the regular none array operators is there a way to tell the operator to just call the destructors without releasing the memory?
One thing I did notice was that the new operator for an array will actually use the first 4 bytes to store the size of the array (I only tested this in visual studio with a 32 bit build) That would help me know how many elements the array has but there is still one problem. What if the array is a pointer array? for example:
Test **arr2 = new Test*[10];
Could someone help me out with these questions please.
It's normal and expected to directly invoke the destructor to destroy objects you've created with placement new. As far as any other way to do things, about the only obvious alternative is to use an Allocator object (which, at least 99% of the time, will just be a wrapper around placement new and directly invoking the destructor).
Generally speaking, you do not want to use new[] at all. You typically want to allocate your raw memory with operator new (or possibly ::operator new) and release it with the matching operator delete or ::operator delete.
You create objects in that memory with placement new and destroy them by directly invoking the destructor.
There is no other way to do it but to explicitly call the destructor as delete will also attempt to free the memory.
Using preallocated memory with placement new should be fairly rare in your code - a typical use case is when you're dealing with direct memory mapped hardware interfaces when you want/need to map an object on top of a fixed memory address - and is something I'd normally consider a code smell.
If you want to tweak the memory management for a specific class, you're much better off either using an STL container with a custom allocator or overload operators new and delete for that specific class.
Yes, this is the only way to do it. There is an asymmetry in being allowed to define new but not delete. [ Well, you can do the latter but it can only get called when new throws an exception (not handled properly below!)
You can use a templated destroy to achieve the same result:
class Test
{
public:
Test() {
printf("In Constructor\n");
}
~Test() {
printf("In Destructor\n");
}
int val;
};
class Allocator
{
public:
static void* allocate(size_t amount) { return std::malloc(amount);}
static void unallocate(void* mem) { std::free(mem);}
static Allocator allocator;
};
Allocator Allocator::allocator;
inline void* operator new(size_t size, const Allocator& allocator)
{
return allocator.allocate(size);
}
template<class T>
void destroy(const Allocator& allocator, T* object)
{
object->~T();
allocator.unallocate(object);
}
int main()
{
Test* t = new (Allocator::allocator) Test();
destroy(Allocator::allocator, t);
return 0;
}