看到参考Vk实现的内存分配器中调用到的几个对齐内存分配函数还蛮有兴趣的,于是自己尝试实现了一下
有一个比较大的问题是不知道std里的_aligned_realloc具体是怎样实现的,自己用先free再malloc的方法乱写了一个,但是发现在简单测试下和调用std中的函数结果是相似的。。。?都能做到不改变指针的值,还请了解这方面的先辈指导一下…
顺便,jetbrain系的某些代码强制格式实在不太好受,,
//
// Created by LCBHSStudent on 2020/1/30.
//
#include <malloc.h>
#include <myusing/myusing.h>
void* aligned_malloc(size_t size, size_t alignment) {
if(alignment & (alignment - 1)) {
return nullptr;
}
//维护FreeBlock(void)指针占用的内存大小-----用sizeof获取
int pSize = sizeof (void*);
// 求得让FreeBlock
// 内存对齐所需要的内存大小
unsigned requestedSize = size + alignment - 1 + pSize;
// 分配的大小
void* rawMemory = malloc(requestedSize);
// 实际分配的内存地址(差不多就是指针运算数字形式)
uintptr_t start = (uintptr_t )rawMemory + pSize;
// 此处的 & 能高位保留,是由于~导致其他位无关位都变成了1
void* aligned = (void*)((start + alignment - 1) & ~(alignment-1));
// 维护一个指向malloc()真正分配的内存的指针
*(void**) ((uintptr_t) aligned - pSize) = rawMemory;
return aligned; //因为做了向上的舍入,所以不需要多余的清理操作
// 这样分配出的内存,对齐填充位于最前,后面紧跟维护指针,再后就是对象的chain
}
void aligned_free(void* aligned) {
void* rawMemory = *(void**) ((uintptr_t)aligned - sizeof(void*));
free(rawMemory);
}
bool isAligned(void* data, unsigned alignment) {
return ((uintptr_t) data & (alignment - 1)) == 0;
}
void* aligned_realloc(void* data, size_t size, size_t alignment) {
if(isAligned(data,
static_cast<int> (alignment)
)) {
aligned_free(data);
return aligned_malloc(size, alignment);
} else {
return nullptr;
}
}
下面是简单实现的vkAllocator
//
// Created by LCBHSStudent on 2020/1/29.
//
#ifndef VULKANDEMO_VKALLOCATOR_H
#define VULKANDEMO_VKALLOCATOR_H
#include <myusing/myusing.h>
#include <vulkan/vulkan.h>
class VkAllocator {
public:
inline explicit operator VkAllocationCallbacks () const {
VkAllocationCallbacks result;
{
result.pUserData = (void*) this;
result.pfnAllocation = &Allocation;
result.pfnReallocation = &ReAllocation;
result.pfnFree = &Free;
result.pfnInternalAllocation = nullptr;
result.pfnInternalFree = nullptr;
}
return result;
}
private:
static void* VKAPI_CALL Allocation(
void* pUserData,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
static void* VKAPI_CALL ReAllocation(
void* pUserData,
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
static void VKAPI_CALL Free(
void* pUserData,
void* pMemory);
void* Allocation(
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
void* ReAllocation(
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
void Free(void* pMemory);
};
#endif //VULKANDEMO_VKALLOCATOR_H
//
// Created by LCBHSStudent on 2020/1/29.
//
#include <cassert>
#include "VkAllocator.h"
void* VkAllocator::Allocation(size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope
)
{
auto ret = aligned_malloc(size, alignment);
assert(ret == nullptr);
return ret;
}
void* VKAPI_CALL VkAllocator::Allocation(
void* pUserData,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return static_cast<VkAllocator*>(pUserData)->Allocation(size,
alignment,
allocationScope);
}
void* VkAllocator::ReAllocation(
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return aligned_realloc(pOriginal, size, alignment);
}
void* VKAPI_CALL VkAllocator::ReAllocation(
void* pUserData,
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return static_cast<VkAllocator*>(pUserData)->ReAllocation(
pOriginal, size, alignment, allocationScope);
}
void VkAllocator::Free(void *pMemory) {
aligned_free(pMemory);
}
void VKAPI_CALL VkAllocator::Free(
void* pUserData,
void* pMemory)
{
return static_cast<VkAllocator*>(pUserData)->Free(pMemory);
}