我正在读一本有关制作游戏引擎的书,因为我想创建自己的书,在书中它建议编写自己的自定义分配器,所以我从书中所描述的出发,并制作了一个基于堆栈的双端分配器。该书还提到,所有分配器都应能够分配对齐的内存。我在理解这本书为何实施对齐方式方面遇到了一些麻烦。本书中有一个函数,它接受您要分配的数量的大小以及对齐的大小。它说对齐方式应该永远只有2的幂,这是我开始无法获得的,并且还确保它不能大于128。我的问题是为什么?我有一个叫做Sprite的类,sizeof(Sprite)=136。假设我想用一个Sprite和一个int构造一个结构。对齐方式是什么,因为sizeof(Sprite)为136,sizeof(int)为4。在这种情况下,应该对齐什么?如何使用这种方法?
编辑: 我读了“内存对齐的目的”,那里的答案根本没有帮助我。我了解内存对齐的目的以及32位内存应如何对齐4字节。我也知道4字节对齐的内存驻留在4倍整数(即0x0、0x4、0x8或0xC)的半字节地址上。我只是不明白当我拥有136字节的内存(与我的Sprite类的情况一样)并且与4字节的int具有相同的结构时会发生什么。我还想知道为什么该方法要求对齐方式为2的幂且小于128。
以下是对齐代码:
// Allocate memory in an efficient way which means aligning it
// IMPORTANT: the alignment must be a power of 2 (usually 4 or 16)
void* DESA::allocAligned(size_t size_bytes, size_t alignment, unsigned int flag) {
assert(flag == LEFT | flag == RIGHT);
assert(alignment >= 1);
assert(alignment <= 128);
assert((alignment & (alignment - 1)) == 0); // Make sure it's a power of 2
// Total amount of bytes
size_t expandedSize_bytes = size_bytes + alignment;
// Allocate unaligned memory and convert to uintptr_t
// allocUnaligned just increments a pointer
std::uintptr_t rawAddress;
if (flag == LEFT)
rawAddress = reinterpret_cast<std::uintptr_t>(allocUnaligned(expandedSize_bytes, LEFT));
else if (flag == RIGHT)
rawAddress = reinterpret_cast<std::uintptr_t>(allocUnaligned(expandedSize_bytes, RIGHT));
// Calculate misalignment
size_t mask = alignment - 1;
std::uintptr_t misalignment = rawAddress & mask;
std::ptrdiff_t adjustment = alignment - misalignment;
// Calculate the adjusted address
std::uintptr_t alignedAddress = rawAddress + adjustment;
// Store the adjustment in the byte immediately preceding the adjusted address
assert(adjustment < 256);
U8* pAlignedMem = reinterpret_cast<U8*>(alignedAddress);
pAlignedMem[-1] = static_cast<U8>(adjustment);
return static_cast<void*>(pAlignedMem);
}