📄 memoryblock.cpp
字号:
{
i = header->blockSize / recordSize;
}
else
{
i = freeRecord - firstHeaderRecord;
i /= recordSize;
}
//
//---------------------------------------------------------------------
// Move the pointer to where the last entry for this block should be if
// all used records where later deleted. If this is an impossible
// location, or if the addresses do not match, this block cannot be
// collapsed
//---------------------------------------------------------------------
//
BYTE **end = start + i - 1;
if (
end - deletions >= deletion_count
|| *end !=
Cast_Pointer(BYTE*, header) + sizeof(*header) + (i-1)*recordSize
)
{
goto Real_Block;
}
//
//------------------------------------------------------------------
// This block may now be killed, but save the next block address for
// further checking
//------------------------------------------------------------------
//
MemoryBlockHeader *next_block = header->nextBlock;
delete header;
//
//-----------------------------------------------------------------------
// Now, move everything following our section of deleted records to where
// our section begins, but only if there is something to move
//-----------------------------------------------------------------------
//
++end;
j =
Cast_Pointer(BYTE*, &deletions[deletion_count])
- Cast_Pointer(BYTE*, end);
deletion_count -= i;
if (j>0)
{
memmove(start, end, j);
}
//
//----------------------------
// Check the next header block
//----------------------------
//
header = next_block;
}
//
//--------------------------------------------------------------------
// Now, clean up the deletion array and reset all the current deletion
// pointers
//--------------------------------------------------------------------
//
deletion = NULL;
for (i=0; i<deletion_count; ++i)
{
Check_Pointer(deletions[i]);
*Cast_Pointer(BYTE**, deletions[i]) = deletion;
deletion = deletions[i];
}
deletedRecord = deletion;
delete[] deletions;
//
//--------------------------------------------------------------------------
// Set the rest of the pointers to deal with this new last block if the last
// block is different than what it used to be. Note that this block should
// be marked as full
//--------------------------------------------------------------------------
//
last_real_block->nextBlock = NULL;
if (
firstHeaderRecord !=
Cast_Pointer(BYTE*, last_real_block) + sizeof(*last_real_block)
)
{
blockSize = last_real_block->blockSize;
firstHeaderRecord =
Cast_Pointer(BYTE*, last_real_block) + sizeof(*last_real_block);
freeRecord = firstHeaderRecord + blockSize;
}
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//
// This function allocates a fixed blockSize record from the record blocks
//
//#############################################################################
//
void*
MemoryBlock::New()
{
void *result;
#if defined(MEMORY_VERIFY)
result = new(blockHeap) char[recordSize];
#else
//
//----------------------------------------------------------------------
// If we have a deletedRecord record, go ahead and reuse it, updating the next
// deletedRecord record value from the firstHeaderRecord one. This chain is independant
// of the firstHeaderRecord record block. If not, grow the blockMemory block by one
// record
//----------------------------------------------------------------------
//
Check_Object(this);
if (deletedRecord)
{
result = deletedRecord;
deletedRecord = *Cast_Pointer(BYTE**, deletedRecord);
}
else
{
result = Grow();
}
#endif
//
//----------------------------------------------------------------------
// If we are checking for unassigned variables, initialize the allocated
// memory with NANs
//----------------------------------------------------------------------
//
#if defined(_ARMOR)
Flood_Memory_With_NAN(result, recordSize);
#endif
//
//-------------------------------------
// Return the address of the new record
//-------------------------------------
//
return result;
}
//
//#############################################################################
//
// This function deallocates a record, making it available for re-use
//
//#############################################################################
//
void
MemoryBlock::Delete(
void* where
)
{
#if defined(MEMORY_VERIFY)
delete where;
#else
//
//--------------------------------------------------------------------
// If we are in debug2 mode, check to see if the deletedRecord region really
// belongs to us
//--------------------------------------------------------------------
//
Check_Object(this);
#if defined(MEMORY_BLOCK_VERIFY)
//
//--------------------------------------------------------------------
// Make sure the address of this record is not already in the deletion
// chain
//--------------------------------------------------------------------
//
void *record;
for (
record = deletedRecord;
record;
record = *Cast_Pointer(BYTE**, record)
)
{
if (record == where)
{
break;
}
}
Verify(!record);
//
//------------------------------------------------------------------
// Find the address of the first record block, then check each block
// until we come to the end of the chain
//------------------------------------------------------------------
//
unsigned
offset;
MemoryBlockHeader*
block = blockMemory;
while (block)
{
//
//---------------------------------------------------------------
// If the record is in this block and is positioned correctly, go
// ahead and break as we have found a legal place within a block
//---------------------------------------------------------------
//
Check_Object(block);
offset =
static_cast<unsigned>(
Cast_Pointer(BYTE*, where) - Cast_Pointer(BYTE*, block + 1)
);
if (offset < block->blockSize)
{
Verify(!(offset % recordSize));
break;
}
//
//---------------------
// Go to the next block
//---------------------
//
block = block->nextBlock;
}
Verify(block);
//
//-----------------------------------------------------------
// Now make sure that the address is not in our future region
//-----------------------------------------------------------
//
Verify(block->nextBlock || offset < freeRecord-firstHeaderRecord);
#endif
//
//----------------------------------------------------------------------
// Make the first few bytes of the record act as the link pointer to the
// beginning of the firstHeaderRecord deletedRecord chain, then make the first record
// available for reuse this one
//----------------------------------------------------------------------
//
*Cast_Pointer(BYTE**, where) = deletedRecord;
deletedRecord = Cast_Pointer(BYTE*, where);
#endif
}
//
//#############################################################################
//#############################################################################
//
void*
MemoryBlock::operator[](size_t index)
{
#if defined(MEMORY_VERIFY)
STOP(("MemoryBlock::operator[] not available!\n"));
#endif
//
//------------------------------------------------------------------
// Find the address of the first record block, then check each block
// until we come to the end of the chain
//------------------------------------------------------------------
//
Check_Object(this);
MemoryBlockHeader
*block = blockMemory;
while (block)
{
//
//---------------------------------------------------------------
// If the index is in this block, go ahead and return its address
//---------------------------------------------------------------
//
Check_Object(block);
Verify(recordSize);
int
records = block->blockSize / recordSize;
if (index < records)
{
return Cast_Pointer(BYTE*, block + 1) + index * recordSize;
}
//
//--------------------------------------------------------------------
// Save the address of the next blockMemory block, then delete this one and
// get ready to delete the next one
//--------------------------------------------------------------------
//
index -= records;
block = block->nextBlock;
}
//
//-----------------------------------------
// The record doesn't exist, so return NULL
//-----------------------------------------
//
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
void*
MemoryStack::Push(const void* what)
{
Check_Object(this);
Check_Pointer(what);
BYTE *block = firstHeaderRecord;
topOfStack = freeRecord;
BYTE *target = static_cast<BYTE*>(Grow());
Mem_Copy(
target,
what,
recordSize,
blockSize - (target - firstHeaderRecord)
);
if (firstHeaderRecord != block)
{
topOfStack = firstHeaderRecord;
}
return topOfStack;
}
//
//#############################################################################
//#############################################################################
//
void*
MemoryStack::Push()
{
Check_Object(this);
BYTE *block = firstHeaderRecord;
topOfStack = freeRecord;
Grow();
if (firstHeaderRecord != block)
{
topOfStack = firstHeaderRecord;
}
return topOfStack;
}
//
//###########################################################################
//###########################################################################
//
void
MemoryStack::Pop()
{
MemoryBlockHeader
*block,
*new_block;
//
//-----------------------------------------
// Make sure that something is in the stack
//-----------------------------------------
//
Check_Object(this);
if (topOfStack)
{
//
//--------------------------------------------------------------------
// If the topOfStack of the stack is not at the bottom of a blockMemory block, the
// freeRecord and topOfStack pointers can move normally
//--------------------------------------------------------------------
//
if (topOfStack != firstHeaderRecord)
{
//
//-------------------------------------------------------------------
// If the freeRecord pointer is at the bottom of a block, we have to delete
// the block and update the variables to the previous block
//-------------------------------------------------------------------
//
if (freeRecord == firstHeaderRecord)
{
new_block =
Cast_Pointer(MemoryBlockHeader*, firstHeaderRecord - 1);
Check_Object(new_block);
for (
block = blockMemory;
block->nextBlock != new_block;
block = block->nextBlock
)
{
Check_Object(block);
}
delete new_block;
block->nextBlock = NULL;
firstHeaderRecord = Cast_Pointer(BYTE*, block + 1);
blockSize = block->blockSize;
}
//
//-----------------------------------------------
// Move the topOfStack and freeRecord pointers back one record
//-----------------------------------------------
//
freeRecord = topOfStack;
topOfStack -= recordSize;
}
//
//--------------------------------------------------------------------
// Otherwise, we have to wrap the top of the stack pointer back to the
// previous block. If there is only one allocated block, then the
// stack is empty
//--------------------------------------------------------------------
//
else if (!blockMemory->nextBlock)
{
topOfStack = NULL;
}
//
//--------------------------------------------------------------------
// Point the top of the stack to the last record of the previous block
//--------------------------------------------------------------------
//
else
{
new_block = Cast_Pointer(MemoryBlockHeader*, firstHeaderRecord - 1);
Check_Object(new_block);
for (
block = blockMemory;
block->nextBlock != new_block;
block = block->nextBlock
)
{
Check_Object(block);
}
topOfStack =
Cast_Pointer(BYTE*, block + 1) + block->blockSize - recordSize;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -