内存管理器-访问冲突写入位置异常
Memory Manager - Access Violation Writing Location Exception
我一直在做一些关于游戏引擎开发的研究,最终我开始尝试编写一个Memorymanager。我从Eberly的游戏引擎设计书中得到了这个想法。在构造函数中,我分配了一个内存块,并添加了一个页眉和页脚,它们都有size属性并已使用。但现在我得到了一个Access写作空缺。我已经听说指针是const并且只能读取,但我不知道如何解决这个问题。
这是MemoryManager.h文件:
// MemoryManager.h - Header file //
#ifndef H_MemoryManager
#define H_MemoryManager
#include "IMemoryManager.h"
class HeaderBlock
{
public:
bool Used;
unsigned int Size;
HeaderBlock* Prev;
HeaderBlock* Next;
};
class FooterBlock
{
public:
bool Used;
unsigned int Size;
};
class MemoryManager : public IMemoryManager
{
private:
int m_MemoryBudget;
char* m_FullMemory;
HeaderBlock* m_FreeBlock;
int m_hsize; // Size of the header
int m_fsize; // Size of the footer
int m_hfsize; // Size of the HeaderandFooter
public:
// Constructor and Destructor
MemoryManager(int Budget);
virtual ~MemoryManager();
// Functions
virtual char* Allocate(unsigned int RequestSize);
virtual char* Deallocate(char* pDeallocate);
HeaderBlock* SearchByPolicy(unsigned int RequestSize);
};
#endif
以下是构造函数的实现:
MemoryManager::MemoryManager(int Budget)
{
m_MemoryBudget = Budget;
m_FullMemory = (char*)malloc(m_MemoryBudget);
m_hsize = sizeof(HeaderBlock);
m_fsize = sizeof(FooterBlock);
m_hfsize = m_hsize + m_fsize;
HeaderBlock* header = (HeaderBlock*)m_FullMemory;
header->Used = false;
header->Size = m_MemoryBudget;
FooterBlock* footer = (FooterBlock*)(m_FullMemory + m_MemoryBudget - m_fsize);
footer->Used = false;
footer->Size = m_MemoryBudget;
header->Prev = header;
header->Next = header;
m_FreeBlock = (HeaderBlock*)m_FullMemory;
}
这是我在错误中得到错误的分配方法
usedHeader->Used = true;
usedFooter->Used = true;
freeHeader->Used = false;
freeFooter->Used = false; // HERE I GET THE EXCEPTION
char* MemoryManager::Allocate(unsigned int RequestSize)
{
HeaderBlock* header = SearchByPolicy(RequestSize);
if(header == NULL)
{
return NULL;
}
unsigned int Size = header->Size;
FooterBlock* footer = (FooterBlock*)((header + Size - m_fsize));
// 1.The size to be allocated fits EXACTLY in the Block pointed by header.
if(Size == RequestSize + m_hfsize)
{
char* allocated = (char*)header + m_hsize;
header->Used = true;
footer->Used = true;
if(header->Next == header)
{
// This is the only block on the free list
m_FreeBlock = 0;
}
else
{
m_FreeBlock->Prev->Next = m_FreeBlock->Next;
m_FreeBlock->Next->Prev = m_FreeBlock->Prev;
m_FreeBlock = m_FreeBlock->Next;
}
return allocated;
}
// 2. The block has more storage than is needed for the allocation request.
if(Size >= RequestSize + 2*m_hfsize)
{
char* allocated = (char*)(header + m_hsize);
// Split the block in a "Used"-Block and a "Free"-Block
HeaderBlock* usedHeader = header;
FooterBlock* usedFooter = (FooterBlock*)(header + m_hsize + RequestSize);
HeaderBlock* freeHeader = (HeaderBlock*)(usedFooter + m_fsize);
FooterBlock* freeFooter = footer;
usedHeader->Used = true;
usedFooter->Used = true;
freeHeader->Used = false;
freeFooter->Used = false;
unsigned int usedSize = RequestSize + m_hfsize;
freeHeader->Size = header->Size - usedSize;
usedHeader->Size = usedSize;
freeHeader->Prev = header->Prev;
freeHeader->Next = header->Next;
m_FreeBlock = freeHeader;
return allocated;
}
// 3. The block has more storage then the Request, but to less to divide into two blocks.
char* allocated = (char*)header + m_hsize;
header->Used = true;
footer->Used = true;
//Detach from the free list;
if(header->Next == header)
{
// This is the only block on the free list
m_FreeBlock = 0;
}
else
{
m_FreeBlock->Prev->Next = m_FreeBlock->Next;
m_FreeBlock->Next->Prev = m_FreeBlock->Prev;
m_FreeBlock = m_FreeBlock->Next;
}
return allocated;
}
我已经检查过SearchByPolicy函数是否返回了一个有效的指针,如果它能找到比请求更大的内存块,它确实会返回一个有效指针。
我希望你能帮助我!
您的问题是指针算术:
FooterBlock* footer = (FooterBlock*)((header + Size - m_fsize));
指
FooterBlock* footer = (FooterBlock*)((uint_ptr)header + (sizeof(HeaderBlock) * Size) - (sizeof(HeaderBlock) * m_fsize));
你很可能想要:
uint_ptr ofs = (uint_ptr)header;
FooterBlock* footer = (FooterBlock*)((ofs + Size - m_fsize));
您可以在stdint.h
中找到uint_ptr
,或者在windows.h
中找到UINT_PTR
更新:
根据评论中的问题
IMemoryManager* memorymanager = new MemoryManager(1000000);
Logger* logger = (Logger*)memorymanager->Allocate(sizeof(Logger));
logger->WriteToBuffer(log, "HOI");
这将失败,因为Logger
的构造函数将不会被调用,有几种方法可以解决这个问题:
- 调用构造方法,但不是很好
- 使用新放置:
(不幸的是,列表破坏了代码格式,所以我必须在这里插入这个…)
IMemoryManager* memorymanager = new MemoryManager(1000000);
Logger* logger = new (memorymanager->Allocate(sizeof(Logger))) ();
logger->WriteToBuffer(log, "HOI");
- 在全局范围内重载
::new
和::delete
运算符(非常糟糕) - 创建一个可继承对象来重载
new
和delete
:
这要求内存管理器在该点可用(或作为参数传递):
class PoolObject
{
void* operator new (std::size_t n)
{
return memorymanager->Allocate(n);
}
void operator delete (void* p)
{
memorymanager->Free(p);
}
}
class Logger : PoolObject
{
}
Logger* logger = new Logger();
相关文章:
- (此函数用于计算 SMA).在 FA.exe 中0x00509159引发异常: 0xC0000005:访问冲突读取位置0
- 内存位置出现Microsoft C++异常:std::out_of_range
- 0x0F50DF58:0xC0000005:访问冲突读取位置0x0047CA04时未处理的异常
- 错误 在测试.exe 0x76C9FD62时出现未经处理的异常:Microsoft C++异常:内存位置0x006FF8
- 如何找出浮点异常的位置
- C 获取std :: out_of_range异常的位置
- cv:内存位置的异常 - 运行 openCV 代码 Visual Studio 2013 & Visual Studio 2017 - Windows 7
- Microsoft C++异常runtime_error在内存位置(代码 0x75A818A2)
- 在 "<name>.exe" 中0x00007FFF168E1657 (vcruntime140d.dll) 引发异常:0xC0000005:访问冲突写入位置0x0000000000000
- 未经治疗的异常访问违规写作位置
- cv::内存位置出现异常错误
- 如何在 VS C++ 中查找发生异常的位置
- 在cv::Mat对象上循环时,内存位置出现cv::异常
- 如何修复<程序名称>中的"<内存位置>未处理的异常。Visual Studio 2017 中的访问冲突写入位置<内存位置>"
- OpenGL:glDrawArrays()引发异常(nvoglv32.dll)读取位置0x00000000时发生访问冲突
- 内存管理器-访问冲突写入位置异常
- 内存位置异常:boost::archive::archive_exception
- 内存位置异常
- 在循环中的内存位置异常:std::bad_alloc
- Opencv PCA Microsoft c++ exception: cv::内存位置异常