指针地址对齐

本文详细介绍了C++中的内存对齐功能,通过aligned_malloc和aligned_free函数实现对象实例的内存分配和释放,同时展示了如何检查内存是否正确对齐以及使用aligned_malloc1和aligned_free1的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值