I am writing an allocator (for simplicity, let's assume nothing fails or throws):
struct AllocationHeader
{
std::size_t size;
std::size_t align;
};
void *aligned_allocate(std::size_t requested_size, std::size_t alignment)
{
constexpr auto header_size = sizeof(AllocationHeader);
const auto total_size = header_size + requested_size + alignment;
auto alloced_ptr = ::new unsigned char[total_size];
::new (alloced_ptr) AllocationHeader{requested_size, alignment};
auto ret_ptr = static_cast<void *>(alloced_ptr + header_size);
auto remaining_size = total_size - header_size;
return std::align(alignment, requested_size, ret_ptr, remaining_size);
}
When I deallocate I want to recover the planted metadata
void aligned_deallocate(void *ptr)
{
constexpr auto header_size = sizeof(AllocationHeader);
// surely this is wrong
auto header_start = reinterpret_cast<unsigned char *>(ptr) - header_size;
auto header = reinterpret_cast<AllocationHeader *>(header_start);
do_something_with(header->size, header->align);
// rest of deallocation...
}
But surely the conversion back to AllocationHeader
is wrong. The original align
could in theory be anything (assuming power of 2) including > std::max_align_t
.
So how do I portably recover how much std::align()
shifted the pointer by? I'm limited to C++11.
EDIT:
I suppose I can do the shifting first:
void *aligned_allocate(std::size_t requested_size, std::size_t alignment)
{
constexpr auto header_size = sizeof(AllocationHeader);
const auto total_size = header_size + requested_size + alignment;
auto alloced_ptr = ::new unsigned char[total_size];
auto ret_ptr = static_cast<void *>(alloced_ptr + header_size);
auto remaining_size = total_size - header_size;
std::align(alignment, requested_size, ret_ptr, remaining_size);
::new (reinterpret_cast<unsigned char *>(ret_ptr) - header_size) AllocationHeader{requested_size, alignment};
return ret_ptr;
}
But then AllocationHeader
may constructed misaligned...
Aucun commentaire:
Enregistrer un commentaire