authentec authentec - 29 days ago 6
C++ Question

How to safely construct a C++ object in malloc'ed memory with a header object

I want to construct arbitrary C++ objects in memory returned by another allocator (which usually calls realloc internally). I know it's generally fine to do a placement new into malloc'ed memory. However, I want all C++ objects to have another common object before it in contiguous allocated memory. This header object will contain information about the following C++ object. I don't know that it is safe, from an alignment standpoint, to allocate (sizeof(header) + sizeof(type)) memory and then construct type at (mem + sizeof(header)). I think it isn't because (mem + sizeof(header)) isn't guaranteed to be properly aligned for type.

I have mulled possibilities such as generating a template type that declares the header followed by type T and allocating

sizeof(ObjPlusHeader<T>)
. However, the problem is that the structure will appear in another part of my code as a void* (mandated by an external library I don't control) so I have to KNOW what to cast it to. I want to cast to Header* not to
ObjectPlusHeader<???>*
.

I know with Standard Layout types I can cast an object to a pointer to its first member. However, T is not necessarily Standard Layout in which case
ObjectPlusHeader<T>
will not be Standard Layout either even if Header is. I also considered making the wrapper template derive publicly from Header and privately from T instead of containing T. However, it still wouldn't be legal to cast the void* directly to a Header* without first casting to the actual type that was stored which I will not know.

What I want is contiguous memory allocated by the allocator (essentially realloc) where I know Header is at the beginning and the arbitrary C++ object follows at some properly aligned address >= mem + sizeof(Header) that I know and can store in the Header. So given the void* I can cast it to Header* and obtain the object. However, I'm unsure about the potential alignment issues.

Answer

just write a (constexpr) function to calculate proper padding:

template<typename T>
size_t paddingAfterHeader() {
   auto rem = sizeof(Header)%alignof(T);
   return rem ? alignof(T) - rem : 0; 
}

allocation:

void *mem = malloc( sizeof( Header ) + paddingAfterHeader<T>() + sizeof(T) );
Comments