c++ - 内存池和 <Unable to read memory>

标签 c++ winapi

我最近将我的项目切换为使用我自己编写的线性内存分配器(用于学习)。当我初始化分配器时,我将一个指针传递给它,该指针指向一个预先被 VirtualAlloc-ed 的内存块。在编写分配器之前,我直接使用这个 block 就好了。

在我的测试用例中,我使用分配器在最初的大内存块中为 Player* 分配内存。为了确保一切正常,我尝试像以前一样直接访问内存块,以确保值按照我的预期进行更改。那是我遇到内存访问错误的时候。使用 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();
};

Player 和 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 结构中设置值后发生了变化。如有任何帮助,我们将不胜感激!

最佳答案

看起来这是你的问题:

simulationMemory = LinearAllocator(simulationAllocationSize, 
   &memory->transientStorage + (uint8_t)0);

有一只流浪猫&运算符,导致您分配的内存不是来自 memory->transientStorage 的已分配内存块指向但来自哪里memory自己活着。

这轮流导致写入p->pos.x覆盖 transientStorage 的值.

调用LinearAllocator应该只是

simulationMemory = LinearAllocator(simulationAllocationSize, 
   memory->transientStorage + (uint8_t)0);

关于c++ - 内存池和 <Unable to read memory>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46436749/

相关文章:

C++ 映射删除(开始、结束)不起作用

c++ - 指针的模板数组类

c++ - 输入/vector 数组不适用于 SendInput

c# - 在 windows xp 下检测刷新 Action

c++ - WASAPI 阻止 Windows 自动挂起?

c++ - 全景影像构建

c++ - 如果参数不是来自末尾,文档在哪里说明您不能从 QT 信号槽连接中删除参数?

windows - 在 Windows 10 周年纪念版中显示触摸键盘 (TabTip.exe)

c++ - GetModuleFileNameEx,拒绝访问错误

c++ - _SH_SECURE 和 _SH_DENYWR 有什么区别