我最近将我的项目改为使用我自己编写的线性内存分配器(用于学习)。当我初始化分配器时,我向它传递一个指向事先VirtualAlloc-ed的内存块的指针。在编写分配器之前,我直接使用这个块就好了。
在我的测试用例中,我使用分配器为播放器*分配内存中的初始大块内存。为了确保每个工作正常,我尝试直接访问内存块,就像我以前一样,以确保值根据我的期望而改变。当我遇到内存访问错误时。使用VS调试器/观察窗口,我可以合理地了解发生了什么以及何时发生,但我希望能够帮助解决原因。我将在下面列出相关的代码。
Virtual Alloc调用,后来由memory-> transientStorage
引用win32_State.gameMemoryBlock = VirtualAlloc(baseAddress, (size_t)win32_State.totalSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
分配器定义
struct LinearAllocator {
void* currentPos;
size_t totalSize;
void* startPos;
size_t usedMemory;
size_t numAllocations;
LinearAllocator();
LinearAllocator(size_t size, void* start);
LinearAllocator(LinearAllocator&) = delete;
~LinearAllocator();
void* allocate(size_t size, uint8 alignment);
void clear();
};
播放器和Vec2f定义
struct Player {
Vec2f pos;
bool32 isFiring;
real32 timeLastFiredMS;
};
union Vec2f {
struct {
real32 x, y;
};
real32 v[2];
};
相关分配器实施细节
void* LinearAllocator::allocate(size_t size, uint8_t alignment) {
if (size == 0 || !isPowerOfTwo(alignment)) {
return nullptr;
}
uint8_t adjustment = alignForwardAdjustment(currentPos, alignment);
if (usedMemory + adjustment + size > totalSize) {
return nullptr;
}
uint8_t* alignedAddress = (uint8*)currentPos + adjustment;
currentPos = (void*)(alignedAddress + size);
usedMemory += size + adjustment;
numAllocations++;
return (void*)alignedAddress;
}
inline uint8_t alignForwardAdjustment(void* address, uint8_t alignment) {
uint8_t adjustment = alignment - ( (size_t)address & (size_t)(alignment - 1));
if (adjustment == alignment) {
return 0; // already aligned
}
return adjustment;
}
inline int32_t isPowerOfTwo(size_t value) {
return value != 0 && (value & (value - 1)) == 0;
}
我尝试使用分配器的初始化代码
// **Can write to memory fine here**
((float*)memory->transientStorage)[0] = 4.f;
size_t simulationAllocationSize = memory->transientStorageSize / 2 / sizeof(real32);
simulationMemory = LinearAllocator(simulationAllocationSize, &memory->transientStorage + (uint8_t)0);
for (int i = 0; i < MAX_PLAYERS; i++) {
Player* p = (Player*)simulationMemory.allocate(sizeof(Player), 4);
// **also works here**
((real32*)memory->transientStorage)[0] = 3.f;
p->pos.x = 0.f; // **after this line, I got the unable to read memory error**
p->pos.y = 0.f;
p->isFiring = false;
p->timeLastFiredMS = 0.f;
// **can't write **
((real32*)memory->transientStorage)[0] = 1.f;
}
// **also can't write**
((real32*)memory->transientStorage)[0] = 2.f;
real32 test = ((real32*)memory->transientStorage)[0];
我的假设是我错过了一些明显的东西。但我唯一需要注意的是,它在Player结构中设置一个值后发生了变化。非常感谢任何帮助!
答案 0 :(得分:3)
看起来这是你的问题:
simulationMemory = LinearAllocator(simulationAllocationSize,
&memory->transientStorage + (uint8_t)0);
有一个迷路&
运算符,导致您不是从memory->transientStorage
指向的memory
指向的内存块中分配内存,而是从p->pos.x
本身所在的位置分配内存。
这是轮流导致写入transientStorage
覆盖simulationMemory = LinearAllocator(simulationAllocationSize,
memory->transientStorage + (uint8_t)0);
的值。
对LinearAllocator的调用应该只是
oc rsh