使用STL vector进行内存对齐分配

4

我希望我的向量存储是对齐的(比如说按16字节边界),因此我使用这个分配器作为 memalign()的封装器,我想知道这是否是用于STL向量的正确分配对齐内存的方式。

template <class T , int Alignment=16>
class AlignedAllocator
{
public:
...

    pointer allocate (size_type size, const_pointer *hint = 0) {
        return (pointer) memalign(Alignment, size*sizeof (T));
    };

    void deallocate (pointer p, size_type size) {
        free(p);
    };
...
}

如果没有,是否有可用的实现支持STL容器的对齐分配器?
PS:我使用gcc编译。

为什么没有答案提到alignas?@0xFF这是XY问题的一个实例。你不是真的想要一个对齐的分配器或向量,而更多地是希望类型始终保持对齐。 - Mooing Duck
3个回答

1
函数memalign(3)已经过时,请尝试使用posix_memalign(3)。除此之外,假设您代码中的...表示包含其余所需分配器元素,则您的代码看起来很好。

0

看起来不错。但是如果要将这样的代码移植到BSD和Darwin上,可能会遇到问题。

最好手动编写分配函数,这样更加健壮。只需新建足够大的块并返回对齐指针即可。此外,您还需要编写自定义的释放函数。


1
无法工作,因为您无法确定要“删除”的原始地址。 - Puppy
+1,但是您需要分配足够的额外空间来存储返回的指针,以便能够释放它(即指针->对齐指针转换不能在数学上被还原)。 - David Rodríguez - dribeas
@DeadMG:你只需要存储那些信息。你分配足够的空间:sizeof(T)*size + sizeof(void*) + Alignment-1,并将空间分成:指针前的填充、指针和对齐内存,返回最后一个块的指针。在释放时,你向后移动 sizeof(void*) 并读取原始返回指针的值。 - David Rodríguez - dribeas
没错,但他没有描述任何需要改变释放程序或引入额外开销的需求。 - Puppy

0

这取决于向量实现,它可能选择分配稍大的缓冲区,并在您的数据前面添加一些会破坏对齐的内容。


负面的是,分配策略应完全驻留在向量使用的分配器内部。如果向量需要用于簿记的内存,则必须将其与包含的元素分开分配。 - Giel
1
@Giel:这并不完全正确。向量通常不需要额外的内存,但如果考虑其他容器,比如std::list,整个节点只有一个分配,这意味着即使分配器产生16字节对齐的内存,也不能保证存储的值在16字节边界上。 - David Rodríguez - dribeas
1
@DavidRodríguez-dribeas:啊,是的,你说得对。我看到GNU STL实现使用了allocator::rebind< _List_node<T> >,它有两个指针在实际数据之前。因此,对于std::list来说,它的对齐肯定会被破坏(除非它恰好是sizeof(T*)或sizeof(T*) * 2)。 - Giel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接