Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the storage of trivially copyable objects be safely reallocated with realloc?

I know that trivially copyable objects can safely be copied my malloc into an appropriate storage location1 and that the destination object will have the same value as the source.

Is this also possible with realloc? That is, if realloc some storage containing some objects of type T, and realloc decides to move and copy the block, will the objects in the newly allocated storage be intact and have started their lifetime, and will the lifetime of the objects in the old storage be safely ended?


1 While asking this question, I had assumed that an "appropriate storage location" included uninitialized storage of suitable alignment and size, but as M.M's answer below argues this isn't actually well supported by the standard. That would make realloc questionable since it is always copying into uninitialized storage.

like image 473
BeeOnRope Avatar asked Oct 19 '17 20:10

BeeOnRope


People also ask

What is a trivially copyable object?

Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write() / std::ifstream::read(). In general, a trivially copyable type is any type for which the underlying bytes can be copied to an array of char or unsigned char...

What is triviallycopyable in C++?

If T is a TriviallyCopyable type, provides the member constant value equal true. For any other type, value is false . The only trivially copyable types are scalar types, trivially copyable classes, and arrays of such types/classes (possibly const-qualified, but not volatile-qualified).

What types of objects can be copied with memcpy?

Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write () / std::ifstream::read () . In general, for any trivially copyable type T and an object obj1 of T, the underlying bytes of obj1 can be copied (e.g.

What is the best way to copy objects in C++?

Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write () / std::ifstream::read ().


1 Answers

No, realloc cannot be used to safely move objects, even of trivially copyable types, because realloc cannot create new objects in uninitialized storage.

In particular, according to C++14 [basic.life]/1:

The lifetime of an object of type T ends when:

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

  • the storage which the object occupies is reused or released.

Calling realloc releases or reuses the storage (even if a reallocation doesn't occur, I'd argue, although that is moot for your question). So the lifetime of the objects ends.

The cases when an object is created is covered by [intro.objects]/1:

An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed.

This does not include realloc; so the realloc call ends the lifetime of the old objects and does not create new objects.

Not only does this imply that realloc isn't suitable to copy trivially copyable objects, it also implies that using malloc or operator new(size_t) to obtain uninitialized storage, followed by a memcpy from an existing object into that storage does not create a usable copy of the object as the destination object has also not been created in that case.


See also: reinterpret_cast creating a trivially-default-constructible object, or constructing a trivially copyable object with memcpy for further discussion of the fact that copying bytes to a new location does not create an object in that location.

like image 58
M.M Avatar answered Oct 26 '22 23:10

M.M