template<typename T> char* allocateSomething()
{
return reinterpret_cast<char*>(std::allocator<T>{}.allocate(1));
}
void deallocateSomething(char* mPtr) { delete mPtr; }
struct TestType { ... };
int main()
{
char* ptr{allocateSomething<TestType>()};
deallocateSomething(ptr);
return 0;
}
Is it guaranteed that deallocateSomething(ptr) will free all allocated bytes even if it has no knowledge of the typename T used when calling allocateSomething<T>()?
Or is it necessary to templatize deallocateSomething as well?
EDIT: I manually deal with the construction/destruction of the object.
EDIT 2: Will this work correctly?
template<typename T> char* allocateSomething()
{
return reinterpret_cast<char*>(std::malloc(sizeof(T)));
}
void deallocateSomething(char* mPtr) { std::free(mPtr); }
// ...
Is it guaranteed that deallocateSomething(ptr) will free all allocated bytes even if it has no knowledge of the typename T used when calling allocateSomething()?
No, nothing is guaranteed, it is undefined behaviour.
Or is it necessary to templatize deallocateSomething as well?
Yes, in general.
You must use matching allocation / deallocation methods. If you want to deallocate with delete then you must allocate with new. If you change the allocation so it doesn't use std::allocator (which you have no control over and no idea how it allocates) and instead allocates with new char[sizeof(T)] then you can safely deallocate with delete[] (but not delete! You must use the [])
You have to use matched allocation and free functions. I.E.
malloc with free
new with delete
new[] with delete[]
std::allocator<>::allocate with std::allocator<>::deallocate. Here the default version is specified to use new/delete, but it is not specified if it does some grouping of allocations or not (it could below some size and not above for instance), so what you do could work in an implementation, and not in another.
Related
I'm trying to implement an array class which can be dynamically sized and it will allocate memory without initialising values. My question is relating to how I deallocate the memory later:
Can I implement my code in this way?:
template<typename Type>
class Array {
Type *values;
Array(int size) : values(new (size * sizeof(Type)) char()) {}
~Array() {
delete[] values;
}
}
Or will I need something like this?:
template<typename Type>
class Array {
Type *values;
void *memory;
Array(int size) : memory(new (size * sizeof(Type)) char()), values(memory), size(size) {}
~Array() {
delete[] memory;
}
}
NOTE!!!! I am aware that this will allocate memory without initialising any Type objects. This is the intended behavior of my code. Also the code above is not my complete implementation, it's only the code that will allocate and deallocate the memory because that is what I'm interested in with this question.
Upon further research I found that I should use malloc() and free() to do what I'm trying to do. Thank you to all answers and commenters.
You can use a Type* to make life easier, and use operator new to get memory without constructing objects.
Type* values; //No aliasing/casting issues
Array(int size) : values((Type*)::operator new(sizeof(Type) * size)) //...
~Array() { /*clean up extant objects*/ ::operator delete(values); }
Then you can use placement new and explicit destructor calls to manage the elements. Also, placement new doesn't allocate memory. It constructs an object at the specified address.
Placement new does not actually allocate any memory. It is merely syntax for calling a constructor with already-allocated memory.
In your destructor, you must manually call the destructors for each present element, then deallocate the memory in the same way it was allocated. Be very careful about exceptions.
You should probably use std::allocator<T>::allocate and std::allocator<T>::deallocate, but you could use malloc/free, new char[]/delete[] (char*)arr, or ::operator new/::operator delete.
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;
}
I have a question regarding placement new syntax in C++. Are the following two code snippets functionally equivalent and can be used interchangeably (I am not implying that the second should be used, when the first one is suitable)?
#1
T* myObj = new T();
// Do something with myObj
delete myObj;
#2
char* mem = new char[sizeof(T)];
T* myObj = new (mem) T();
// Do something with myObj
myObj->~T();
delete[] mem;
Is there something I should be especially careful of, when I am using the placement new syntax like this?
They are not equivalent, because they have different behaviour if the constructor or the destructor of T throws.
new T() will free any memory that has been allocated before letting the exception propagate any further. char* mem = new char[sizeof(T)]; T* myObj = new (mem) T(); will not (and unless you explicitly do something to ensure that it gets freed you will have a leak). Similarly, delete myObj will always deallocate memory, regardless of whether ~T() throws.
An exact equivalent for T* myObj = new T();/*other code*/delete myObj; would be something like:
//When using new/delete, T::operator new/delete
//will be used if it exists.
//I don't know how do emulate this in
//a generic way, so this code just uses
//the global versions of operator new and delete.
void *mem = ::operator new(sizeof(T));
T* myObj;
try {
myObj = new (mem) T();
}
catch(...) {
::operator delete(mem);
throw;
}
/*other code*/
try {
myObj->~T();
::operator delete(mem);
}
catch(...) {
//yes there are a lot of duplicate ::operator deletes
//This is what I get for not using RAII ):
::operator delete(mem);
throw;
}
Since you're allocating raw memory, a closer equivalent would be:
void *mem = operator new(sizeof(T));
T *myobj = new(mem) T();
// ...
myobj->~T();
operator delete(mem);
Note that if you've overloaded ::operator new for a particular class, this will use that class' operator new, where yours using new char [] would ignore it.
Edit: though I should add that I'm ignoring the possibility of exceptions here. #Mankarse's answer seems (to me) to cover that part fairly well.
On a fundamental level, you're doing the same thing in both situations: i.e. you're instantiating a new object on the heap and you're releasing the memory, but in the second case you're (obviously) using the placement new operator.
In this case both of them would yield the same results, minus the differences if the constructor throws as Mankarse explained.
In addition, I wouldn't say that you can use them interchangeably, because the second case is not a realistic example of how placement new is used. It would probably make a lot more sense to use placement new in the context of a memory pool and if you're writing your own memory manager so you can place multiple T objects on the per-allocated memory (in my tests it tends to save about 25% CPU time). If you have a more realistic use case for placement new then there will be a lot more things that you should worry about.
Well, you are pre-allocating memory for your T object. And it should be fine. Nevertheless it makes sense if you will reuse allocated area one more time. Otherwise It will be slower.
Yes. Your example is too simple to demonstrate this, but the memory you allocated in advance, "mem," should manage the object stored within, "myObj."
Perhaps put a better way, scenario #1 allocates space on the heap, and constructs an object in that space. Scenario #2 allocates space on the heap, "mem," then constructs an object somewhere within that space.
Now, put a second object somewhere else within "mem." It gets complicated, right?
The construction and destruction of myObj are happening identically in both scenarios (except in the case of your constructor throwing an exception, as pointed out by Mankarse), but the allocator is taking care of your memory management for you in scenario #1, and not in scenario #2.
So, be careful of managing "mem" appropriately. One common approach is the following:
template<class T> void destroy(T* p, Arena& a)
{
if (p) {
p->~T(); // explicit destructor call
a.deallocate(p);
}
}
Having structs like
struct ifoo_version_42 {
int x, y, z;
char *imageData;
};
where imageData is something like imageData = new char[50000];
Can we perform something like:
template< typename T >
void del( T a ) // we promise to use this only on C Plain Old data structs=)
{
delete a;
}
on this structure an will it be enough to clean memory form if?
Deleting the struct does not recursively delete any pointers in it, and hence doesn't free the array of char pointed to by imageData.
I'm also a bit confused by your use of delete[]. You can free an array (allocated with new[]) using delete[], or free a single object (allocated with new) using delete. You can't mix them, and you don't say how you're allocating one or more instances of ifoo_version_42. For example the following has undefined behavior:
ifoo_version_42 *x = new ifoo_version_42;
del(x);
The following is OK:
ifoo_version_42 *x = new ifoo_version_42[1];
del(x);
This function template would also "work" on non-POD types. It's literally no different from invoking delete[] a; directly.
However, this won't delete the memory associated with imageData. That's typically the sort of thing you do in a destructor.
If you perform your del function on an ifoo_version_42, then the memory block pointed to by data will not be freed; neither delete nor delete[] work recursively.
delete[] is meant to be used for freeing arrays; that is, if you allocated imageData with new[], then it should be freed with delete[].
delete is meant to be used for freeing single objects: If you e.g. allocated a ifoo_version_42 with new, then you should free it with delete.
(Also, never use delete for something allocated with malloc(), or free() with something allocated with new.)
One further suggestion: Learn the RAII idiom and use smart pointer classes provided by the STL or Boost libraries; these go a long way towards helping you with correct memory management.
That's pretty much it. I need to allocate memory and pass it to a function that takes a void *. I'd like to use a shared_ptr but I don't know how to do it.
Do you mean something like:
boost::shared_ptr<int> myInt(new int(5));
call_some_function(myInt.get());
This only let's the function use the int*. It shouldn't try to delete it or take ownership.
If you want just raw memory, use a vector:
std::vector<char> memory(blockSize);
call_some_function(&blockSize[0]);
Again, the memory belongs to the vector.
If your function does want ownership, there's no need to wrap it into something, since you won't be managing it:
call_some_function(new int);
call_some_function(new char[blockSize]);
Make sure the function will be releasing it with a call to delete/delete[]. If not (for example, it intends to use free()), you'll need to use malloc instead:
template <typename T>
T* malloc_new(void)
{
void* memory = std::malloc(sizeof(T));
if (!memory)
throw std::bad_alloc();
try
{
return new (memory) T();
}
catch(...)
{
std::free(memory);
throw;
}
}
call_some_function(malloc_new<int>());
call_some_function(malloc(blockSize));
you can also use std::string as a reference counted memory blob container. It is as efficient as shared_ptr on char * vector (maybe better)