Недавно я встретил Howard Hinnant short_alloc, и это самый лучший пример пользовательских распределителей, которые я видел.
Но поскольку я потратил больше времени на изучение кода для его интеграции в моем личном проекте, мне пришло в голову, что класс arena
, предоставляющий распределения на основе стека, может не всегда возвращать правильно выровненную память. На самом деле, я боюсь, что гарантировано, что только первое распределение будет соответствующим образом выровнено (так как сам буфер имеет принудительное выравнивание), см. Ниже соответствующие фрагменты кода:
template <std::size_t N>
class arena
{
static const std::size_t alignment = 16;
alignas(alignment) char buf_[N];
char* ptr_;
//...
};
template <std::size_t N>
char*
arena<N>::allocate(std::size_t n)
{
assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
if (buf_ + N - ptr_ >= n)
{
char* r = ptr_;
ptr_ += n;
return r;
}
return static_cast<char*>(::operator new(n));
}
Я могу придумать несколько способов исправить это (ценой потери памяти), проще всего округлить size
в функции allocate/deallocate
до кратного alignment
.
Но прежде чем что-либо менять, я хотел бы удостовериться, что здесь ничего не пропало...