Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is moving an object into malloc'd memory valid C++?

If memory is allocated with malloc (as opposed to new) and an object is moved into that memory, is that valid C++? Let's say I allocate memory for an array of n objects of type T, and I have a range of n objects of type T that I want to move into that, is this valid:

T* next = (T *)malloc(n*sizeof(T));
T* t = std::begin(my_range);
while (we still have more Ts) {
  *next = std::move(*t);   
  ++next;
  ++t;
}

This seems to work, but I'm curious as to why it would since we never new the objects in the allocated memory that we move to.

My guess is placement new is the correct way to do it:

while (we still have more Ts) {
  new (next) T(*t);
  ++next;
  ++t;
}

but I'd like to know WHY the first one is incorrect, and if so, if it just works by luck or because T happens to be a POD.

like image 339
Philipp Avatar asked Feb 09 '19 01:02

Philipp


People also ask

Does malloc clear the memory?

malloc() does not initialize the memory allocated, while calloc() guarantees that all bytes of the allocated memory block have been initialized to 0.

Can malloc be used for arrays?

defines a named array object. Your pointer declaration and initialization does not. However, the malloc call (if it succeeds and returns a non- NULL result, and if n > 0 ) will create an anonymous array object at run time. But it does not "define an array a ".

Why is malloc better than new?

malloc(): It is a C library function that can also be used in C++, while the “new” operator is specific for C++ only. Both malloc() and new are used to allocate the memory dynamically in heap. But “new” does call the constructor of a class whereas “malloc()” does not.

How can we dynamically allocate memory in C?

In C, dynamic memory is allocated from the heap using some standard library functions. The two key dynamic memory functions are malloc() and free(). The malloc() function takes a single parameter, which is the size of the requested memory area in bytes. It returns a pointer to the allocated memory.


1 Answers

If memory is allocated with malloc (as opposed to new) and an object is moved into that memory, is that valid C++?

Potentially; Not necessarily.

If we consider move-construction then sure, you can use placement-new to create an object into the memory. A bit like in your second example - except the example does a copy; unless the iterator is strange and returns an rvalue. Although, you mention the type being a POD in which case there is no difference between a move and a copy.

If we consider move assignment, then it is well defined only if there has previously been created an object into that memory. In your first example, no objects have been created, so the behaviour is technically undefined.

I'd like to know [...] if it just works by luck or because T happens to be a POD.

Technically UB, but is very likely to work if T is POD. This type of initialisation by assignment is well defined in C (and the only way to create objects dynamically in that language).

If the assignment operator were non-trivial, then stuff would very likely break.


To move a range of objects into uninitialised memory, you'd probably want to use std::uninitialized_move. It'll be well defined regardless of triviality of the type, and you don't even have to write a loop.

like image 84
eerorika Avatar answered Oct 15 '22 02:10

eerorika