#include <iostream>
#include <string.h>
void* aligned_malloc(size_t size, int alignment)
{
constexpr int PointerSize = sizeof(void*);
// alignment - 1 + pointerSize这个是FreeBlock内存对齐需要的内存大小
// sizeof(T) = 20, __alignof(T) = 16
// 那么alignment - 1 + pointSize = 19
const int needSize = size + alignment - 1 + PointerSize;
// 分配的实际大小
void *ptr = malloc(needSize);
printf(" malloc ptr : %p\n", ptr);
// 这里实Pool真正为对象实例分配的内存地址
uintptr_t start = (uintptr_t)ptr + PointerSize;
printf(" start add: %p\n", reinterpret_cast<void**>(start));
// 向上舍入操作
// 解释一下, __ALIGN - 1指明的是实际内存对齐的粒度
// 例如__ALIGN = 8时, 我们只需要7就可以实际表示8个数(0~7)
// 那么~(__ALIGN - 1)就是进行舍入的粒度
// 我们将(bytes) + __ALIGN-1)就是先进行进位, 然后截断
// 这就保证了我是向上舍入的
// 例如byte = 100, __ALIGN = 8的情况
// ~(__ALIGN - 1) = (1 000)B
// ((bytes) + __ALIGN-1) = (1 101 011)B
// (((bytes) + __ALIGN-1) & ~(__ALIGN - 1)) = (1 101 000 )B = (104)D
// 104 / 8 = 13, 这就实现了向上舍入
// 对于byte刚好满足内存对齐的情况下, 结果保持byte大小不变
// 记得《Hacker's Delight》上面有相关的计算
// 这个表达式与下面给出的等价
// ((((bytes) + _ALIGN - 1) * _ALIGN) / _ALIGN)
// 但是SGI STL使用的方法效率非常高
void* aligned = (void*)((start + alignment - 1) & ~(alignment - 1));
printf("aligned ptr : %p\n", aligned);
// 这里维护一个指向malloc()真正分配的内存,
// ------------------------------------------------aligned--------
// -------------aligned-PointerSize----------------aligned
*(void**)((uintptr_t)aligned - PointerSize) = ptr;
return aligned;
}
struct alignas(32) Test
{
char buff[18];
int id;
};
template<typename T>
void aligned_free(T * aligned_ptr)
{
printf("%ld=====\n", sizeof(T*));
if (aligned_ptr)
{
T* ptr = ((T**)aligned_ptr)[-1];
printf("int addr: %p, actual ptr: %p\n", aligned_ptr, ptr);
// free(static_cast<void*>(ptr));
free(((T**)aligned_ptr)[-1]);
}
}
bool isAligned(void* data, int alignment)
{
// 又是一个经典算法, 参见<Hacker's Delight>
return ((uintptr_t)data & (alignment - 1)) == 0;
}
#include <memory>
void* aligned_malloc1(size_t size, size_t alignment)
{
size_t offset = alignment - 1 + sizeof(void*);
void * originalP = malloc(size + offset);
size_t originalLocation = reinterpret_cast<size_t>(originalP);
size_t realLocation = (originalLocation + offset) & ~(alignment - 1);
void * realP = reinterpret_cast<void*>(realLocation);
size_t originalPStorage = realLocation - sizeof(void*);
*reinterpret_cast<void**>(originalPStorage) = originalP;
return realP;
}
void aligned_free1(void* p)
{
size_t originalPStorage = reinterpret_cast<size_t>(p) - sizeof(void*);
free(*reinterpret_cast<void**>(originalPStorage));
}
int main(int argc, char* argv[])
{
int totalsize = 10;
Test* data = (Test*)aligned_malloc(sizeof(int)*totalsize, 32);
if (isAligned(data, 32)) {
std::cout << "isAligned\n";
}
memset(data, 0, sizeof(Test)*totalsize);
data[5].id = 1;
for (int i = 0; i < totalsize; i++) {
std::cout << data[i].id << " ";
}
std::cout << "\n";
aligned_free<Test>(data);
std::cout << "aligned_free\n";
void * p = aligned_malloc1(1024, 64);
printf("0x%p\n", p);
aligned_free1(p);
return 0;
}
04-14
1056

08-22
2216
