Added functions to check for corrupted Chunks and FixedAllocators. Made
several minor coding changes. git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@377 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
fb0f712fde
commit
985f330d3d
1 changed files with 322 additions and 28 deletions
350
src/SmallObj.cpp
350
src/SmallObj.cpp
|
@ -20,12 +20,13 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
//#define DO_EXTRA_LOKI_TESTS
|
//#define DO_EXTRA_LOKI_TESTS
|
||||||
|
//#define USE_NEW_TO_ALLOCATE
|
||||||
|
|
||||||
#ifdef DO_EXTRA_LOKI_TESTS
|
#ifdef DO_EXTRA_LOKI_TESTS
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <bitset>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,11 +109,33 @@ namespace Loki
|
||||||
/// Releases the allocated block of memory.
|
/// Releases the allocated block of memory.
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
bool IsCorrupt( unsigned char numBlocks, std::size_t blockSize ) const;
|
/** Determines if the Chunk has been corrupted.
|
||||||
|
@param numBlocks Total # of blocks in the Chunk.
|
||||||
|
@param blockSize # of bytes in each block.
|
||||||
|
@param checkIndexes True if caller wants to check indexes of available
|
||||||
|
blocks for corruption. If false, then caller wants to skip some
|
||||||
|
tests tests just to run faster. (Debug version does more checks, but
|
||||||
|
release version runs faster.)
|
||||||
|
@return True if Chunk is corrupt.
|
||||||
|
*/
|
||||||
|
bool IsCorrupt( unsigned char numBlocks, std::size_t blockSize,
|
||||||
|
bool checkIndexes ) const;
|
||||||
|
|
||||||
|
/** Determines if block is available.
|
||||||
|
@param p Address of block managed by Chunk.
|
||||||
|
@param numBlocks Total # of blocks in the Chunk.
|
||||||
|
@param blockSize # of bytes in each block.
|
||||||
|
@return True if block is available, else false if allocated.
|
||||||
|
*/
|
||||||
|
bool IsBlockAvailable( void * p, unsigned char numBlocks,
|
||||||
|
std::size_t blockSize ) const;
|
||||||
|
|
||||||
/// Returns true if block at address P is inside this Chunk.
|
/// Returns true if block at address P is inside this Chunk.
|
||||||
inline bool HasBlock( unsigned char * p, std::size_t chunkLength ) const
|
inline bool HasBlock( void * p, std::size_t chunkLength ) const
|
||||||
{ return ( pData_ <= p ) && ( p < pData_ + chunkLength ); }
|
{
|
||||||
|
unsigned char * pc = static_cast< unsigned char * >( p );
|
||||||
|
return ( pData_ <= pc ) && ( pc < pData_ + chunkLength );
|
||||||
|
}
|
||||||
|
|
||||||
inline bool HasAvailable( unsigned char numBlocks ) const
|
inline bool HasAvailable( unsigned char numBlocks ) const
|
||||||
{ return ( blocksAvailable_ == numBlocks ); }
|
{ return ( blocksAvailable_ == numBlocks ); }
|
||||||
|
@ -238,6 +261,14 @@ namespace Loki
|
||||||
*/
|
*/
|
||||||
std::size_t CountEmptyChunks( void ) const;
|
std::size_t CountEmptyChunks( void ) const;
|
||||||
|
|
||||||
|
/** Determines if FixedAllocator is corrupt. Checks data members to
|
||||||
|
see if any have erroneous values, or violate class invariants. It
|
||||||
|
also checks if any Chunk is corrupt. Complexity is O(C) where C is
|
||||||
|
the number of Chunks. If any data is corrupt, this will return true
|
||||||
|
in release mode, or assert in debug mode.
|
||||||
|
*/
|
||||||
|
bool IsCorrupt( void ) const;
|
||||||
|
|
||||||
/** Returns true if the block at address p is within a Chunk owned by
|
/** Returns true if the block at address p is within a Chunk owned by
|
||||||
this FixedAllocator. Complexity is O(C) where C is the total number
|
this FixedAllocator. Complexity is O(C) where C is the total number
|
||||||
of Chunks - empty or used.
|
of Chunks - empty or used.
|
||||||
|
@ -251,7 +282,6 @@ namespace Loki
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Chunk::Init ----------------------------------------------------------------
|
// Chunk::Init ----------------------------------------------------------------
|
||||||
|
|
||||||
bool Chunk::Init( std::size_t blockSize, unsigned char blocks )
|
bool Chunk::Init( std::size_t blockSize, unsigned char blocks )
|
||||||
|
@ -338,7 +368,7 @@ void Chunk::Deallocate(void* p, std::size_t blockSize)
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
// Check if block was already deleted. Attempting to delete the same
|
// Check if block was already deleted. Attempting to delete the same
|
||||||
// block more than once causes Chunk's linked-list of stealth indexes to
|
// block more than once causes Chunk's linked-list of stealth indexes to
|
||||||
// become corrupt. And causes count of blocksAvailable_ ) to be wrong.
|
// become corrupt. And causes count of blocksAvailable_ to be wrong.
|
||||||
if ( 0 < blocksAvailable_ )
|
if ( 0 < blocksAvailable_ )
|
||||||
assert( firstAvailableBlock_ != index );
|
assert( firstAvailableBlock_ != index );
|
||||||
#endif
|
#endif
|
||||||
|
@ -353,38 +383,144 @@ void Chunk::Deallocate(void* p, std::size_t blockSize)
|
||||||
|
|
||||||
// Chunk::IsCorrupt -----------------------------------------------------------
|
// Chunk::IsCorrupt -----------------------------------------------------------
|
||||||
|
|
||||||
bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize ) const
|
bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize,
|
||||||
|
bool checkIndexes ) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( numBlocks < blocksAvailable_ ) return true;
|
if ( numBlocks < blocksAvailable_ )
|
||||||
if ( 0 == blocksAvailable_ ) return false;
|
{
|
||||||
|
// Contents at this Chunk corrupted. This might mean something has
|
||||||
|
// overwritten memory owned by the Chunks container.
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( IsFilled() )
|
||||||
|
// Useless to do further corruption checks if all blocks allocated.
|
||||||
|
return false;
|
||||||
unsigned char index = firstAvailableBlock_;
|
unsigned char index = firstAvailableBlock_;
|
||||||
if ( numBlocks <= index ) return true;
|
if ( numBlocks <= index )
|
||||||
|
{
|
||||||
|
// Contents at this Chunk corrupted. This might mean something has
|
||||||
|
// overwritten memory owned by the Chunks container.
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( !checkIndexes )
|
||||||
|
// Caller chose to skip more complex corruption tests.
|
||||||
|
return false;
|
||||||
|
|
||||||
#ifdef DO_EXTRA_LOKI_TESTS
|
/* If the bit at index was set in foundBlocks, then the stealth index was
|
||||||
std::bitset< 256 > foundBlocks;
|
found on the linked-list.
|
||||||
|
*/
|
||||||
|
std::bitset< UCHAR_MAX > foundBlocks;
|
||||||
unsigned char * nextBlock = NULL;
|
unsigned char * nextBlock = NULL;
|
||||||
|
|
||||||
unsigned char cc = 0;
|
/* The loop goes along singly linked-list of stealth indexes and makes sure
|
||||||
for ( ;; )
|
that each index is within bounds (0 <= index < numBlocks) and that the
|
||||||
|
index was not already found while traversing the linked-list. The linked-
|
||||||
|
list should have exactly blocksAvailable_ nodes, so the for loop will not
|
||||||
|
check more than blocksAvailable_. This loop can't check inside allocated
|
||||||
|
blocks for corruption since such blocks are not within the linked-list.
|
||||||
|
Contents of allocated blocks are not changed by Chunk.
|
||||||
|
|
||||||
|
Here are the types of corrupted link-lists which can be verified. The
|
||||||
|
corrupt index is shown with asterisks in each example.
|
||||||
|
|
||||||
|
Type 1: Index is too big.
|
||||||
|
numBlocks == 64
|
||||||
|
blocksAvailable_ == 7
|
||||||
|
firstAvailableBlock_ -> 17 -> 29 -> *101*
|
||||||
|
There should be no indexes which are equal to or larger than the total
|
||||||
|
number of blocks. Such an index would refer to a block beyond the
|
||||||
|
Chunk's allocated domain.
|
||||||
|
|
||||||
|
Type 2: Index is repeated.
|
||||||
|
numBlocks == 64
|
||||||
|
blocksAvailable_ == 5
|
||||||
|
firstAvailableBlock_ -> 17 -> 29 -> 53 -> *17* -> 29 -> 53 ...
|
||||||
|
No index should be repeated within the linked-list since that would
|
||||||
|
indicate the presence of a loop in the linked-list.
|
||||||
|
*/
|
||||||
|
for ( unsigned char cc = 0; ; )
|
||||||
{
|
{
|
||||||
nextBlock = pData_ + ( index * blockSize );
|
nextBlock = pData_ + ( index * blockSize );
|
||||||
foundBlocks.set( index, true );
|
foundBlocks.set( index, true );
|
||||||
++cc;
|
++cc;
|
||||||
if ( cc >= blocksAvailable_ )
|
if ( cc >= blocksAvailable_ )
|
||||||
|
// Successfully counted off number of nodes in linked-list.
|
||||||
break;
|
break;
|
||||||
index = *nextBlock;
|
index = *nextBlock;
|
||||||
if ( numBlocks <= index )
|
if ( numBlocks <= index )
|
||||||
|
{
|
||||||
|
/* This catches Type 1 corruptions as shown in above comments.
|
||||||
|
This implies that a block was corrupted due to a stray pointer
|
||||||
|
or an operation on a nearby block overran the size of the block.
|
||||||
|
*/
|
||||||
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if ( foundBlocks.test( index ) )
|
if ( foundBlocks.test( index ) )
|
||||||
|
{
|
||||||
|
/* This catches Type 2 corruptions as shown in above comments.
|
||||||
|
This implies that a block was corrupted due to a stray pointer
|
||||||
|
or an operation on a nearby block overran the size of the block.
|
||||||
|
Or perhaps the program tried to delete a block more than once.
|
||||||
|
*/
|
||||||
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( foundBlocks.count() != blocksAvailable_ )
|
if ( foundBlocks.count() != blocksAvailable_ )
|
||||||
|
{
|
||||||
|
/* This implies that the singly-linked-list of stealth indexes was
|
||||||
|
corrupted. Ideally, this should have been detected within the loop.
|
||||||
|
*/
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chunk::IsBlockAvailable ----------------------------------------------------
|
||||||
|
|
||||||
|
bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks,
|
||||||
|
std::size_t blockSize ) const
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( IsFilled() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#else
|
unsigned char * place = static_cast< unsigned char * >( p );
|
||||||
(void)blockSize; // cast as void to make warning go away.
|
// Alignment check
|
||||||
#endif
|
assert( ( place - pData_ ) % blockSize == 0 );
|
||||||
|
unsigned char blockIndex = static_cast< unsigned char >(
|
||||||
|
( place - pData_ ) / blockSize );
|
||||||
|
|
||||||
|
unsigned char index = firstAvailableBlock_;
|
||||||
|
assert( numBlocks > index );
|
||||||
|
if ( index == blockIndex )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* If the bit at index was set in foundBlocks, then the stealth index was
|
||||||
|
found on the linked-list.
|
||||||
|
*/
|
||||||
|
std::bitset< UCHAR_MAX > foundBlocks;
|
||||||
|
unsigned char * nextBlock = NULL;
|
||||||
|
for ( unsigned char cc = 0; ; )
|
||||||
|
{
|
||||||
|
nextBlock = pData_ + ( index * blockSize );
|
||||||
|
foundBlocks.set( index, true );
|
||||||
|
++cc;
|
||||||
|
if ( cc >= blocksAvailable_ )
|
||||||
|
// Successfully counted off number of nodes in linked-list.
|
||||||
|
break;
|
||||||
|
index = *nextBlock;
|
||||||
|
if ( index == blockIndex )
|
||||||
|
return true;
|
||||||
|
assert( numBlocks > index );
|
||||||
|
assert( !foundBlocks.test( index ) );
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -444,16 +580,130 @@ std::size_t FixedAllocator::CountEmptyChunks( void ) const
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FixedAllocator::IsCorrupt --------------------------------------------------
|
||||||
|
|
||||||
|
bool FixedAllocator::IsCorrupt( void ) const
|
||||||
|
{
|
||||||
|
const bool isEmpty = chunks_.empty();
|
||||||
|
ChunkCIter start( chunks_.begin() );
|
||||||
|
ChunkCIter last( chunks_.end() );
|
||||||
|
const size_t emptyChunkCount = CountEmptyChunks();
|
||||||
|
|
||||||
|
if ( isEmpty )
|
||||||
|
{
|
||||||
|
if ( start != last )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( 0 < emptyChunkCount )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( NULL != deallocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( NULL != allocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( NULL != emptyChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const Chunk * front = &chunks_.front();
|
||||||
|
const Chunk * back = &chunks_.back();
|
||||||
|
if ( start >= last )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( back < deallocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( back < allocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( front > deallocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( front > allocChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( emptyChunkCount )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if ( emptyChunk_ != NULL )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if ( emptyChunk_ == NULL )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( back < emptyChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( front > emptyChunk_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( !emptyChunk_->HasAvailable( numBlocks_ ) )
|
||||||
|
{
|
||||||
|
// This may imply somebody tried to delete a block twice.
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for ( ChunkCIter it( start ); it != last; ++it )
|
||||||
|
{
|
||||||
|
const Chunk & chunk = *it;
|
||||||
|
if ( chunk.IsCorrupt( numBlocks_, blockSize_, true ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// FixedAllocator::HasBlock ---------------------------------------------------
|
// FixedAllocator::HasBlock ---------------------------------------------------
|
||||||
|
|
||||||
const Chunk * FixedAllocator::HasBlock( void * p ) const
|
const Chunk * FixedAllocator::HasBlock( void * p ) const
|
||||||
{
|
{
|
||||||
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||||
unsigned char * pc = static_cast< unsigned char * >( p );
|
|
||||||
for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
|
for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
|
||||||
{
|
{
|
||||||
const Chunk & chunk = *it;
|
const Chunk & chunk = *it;
|
||||||
if ( chunk.HasBlock( pc, chunkLength ) )
|
if ( chunk.HasBlock( p, chunkLength ) )
|
||||||
return &chunk;
|
return &chunk;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -601,9 +851,19 @@ bool FixedAllocator::Deallocate( void * p, Chunk * hint )
|
||||||
if ( NULL == foundChunk )
|
if ( NULL == foundChunk )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert( foundChunk->HasBlock( static_cast< unsigned char * >( p ),
|
assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) );
|
||||||
numBlocks_ * blockSize_ ) );
|
#ifdef LOKI_CHECK_FOR_CORRUPTION
|
||||||
assert( !foundChunk->IsCorrupt( numBlocks_, blockSize_ ) );
|
if ( foundChunk->IsCorrupt( numBlocks_, blockSize_, true ) )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( foundChunk->IsBlockAvailable( p, numBlocks_, blockSize_ ) )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
deallocChunk_ = foundChunk;
|
deallocChunk_ = foundChunk;
|
||||||
DoDeallocate(p);
|
DoDeallocate(p);
|
||||||
assert( CountEmptyChunks() < 2 );
|
assert( CountEmptyChunks() < 2 );
|
||||||
|
@ -618,9 +878,7 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
if ( chunks_.empty() ) return NULL;
|
if ( chunks_.empty() ) return NULL;
|
||||||
assert(deallocChunk_);
|
assert(deallocChunk_);
|
||||||
|
|
||||||
unsigned char * pc = static_cast< unsigned char * >( p );
|
|
||||||
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||||
|
|
||||||
Chunk * lo = deallocChunk_;
|
Chunk * lo = deallocChunk_;
|
||||||
Chunk * hi = deallocChunk_ + 1;
|
Chunk * hi = deallocChunk_ + 1;
|
||||||
const Chunk * loBound = &chunks_.front();
|
const Chunk * loBound = &chunks_.front();
|
||||||
|
@ -633,7 +891,7 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
{
|
{
|
||||||
if (lo)
|
if (lo)
|
||||||
{
|
{
|
||||||
if ( lo->HasBlock( pc, chunkLength ) ) return lo;
|
if ( lo->HasBlock( p, chunkLength ) ) return lo;
|
||||||
if ( lo == loBound )
|
if ( lo == loBound )
|
||||||
{
|
{
|
||||||
lo = NULL;
|
lo = NULL;
|
||||||
|
@ -644,7 +902,7 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
|
|
||||||
if (hi)
|
if (hi)
|
||||||
{
|
{
|
||||||
if ( hi->HasBlock( pc, chunkLength ) ) return hi;
|
if ( hi->HasBlock( p, chunkLength ) ) return hi;
|
||||||
if ( ++hi == hiBound )
|
if ( ++hi == hiBound )
|
||||||
{
|
{
|
||||||
hi = NULL;
|
hi = NULL;
|
||||||
|
@ -660,8 +918,12 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
|
|
||||||
void FixedAllocator::DoDeallocate(void* p)
|
void FixedAllocator::DoDeallocate(void* p)
|
||||||
{
|
{
|
||||||
assert( deallocChunk_->HasBlock( static_cast< unsigned char * >( p ),
|
// Show that deallocChunk_ really owns the block at address p.
|
||||||
numBlocks_ * blockSize_ ) );
|
assert( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) );
|
||||||
|
// Either of the next two assertions may fail if somebody tries to
|
||||||
|
// delete the same block twice.
|
||||||
|
assert( emptyChunk_ != deallocChunk_ );
|
||||||
|
assert( !deallocChunk_->HasAvailable( numBlocks_ ) );
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
|
|
||||||
|
@ -874,6 +1136,34 @@ void SmallObjAllocator::Deallocate( void * p )
|
||||||
assert( found );
|
assert( found );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SmallObjAllocator::IsCorrupt -----------------------------------------------
|
||||||
|
|
||||||
|
bool SmallObjAllocator::IsCorrupt( void ) const
|
||||||
|
{
|
||||||
|
if ( NULL == pool_ )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( 0 == GetAlignment() )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( 0 == GetMaxObjectSize() )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||||
|
for ( std::size_t ii = 0; ii < allocCount; ++ii )
|
||||||
|
{
|
||||||
|
if ( pool_[ ii ].IsCorrupt() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Loki
|
} // end namespace Loki
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -887,6 +1177,10 @@ void SmallObjAllocator::Deallocate( void * p )
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// $Log$
|
// $Log$
|
||||||
|
// Revision 1.18 2005/12/08 22:08:20 rich_sposato
|
||||||
|
// Added functions to check for corrupted Chunks and FixedAllocators. Made
|
||||||
|
// several minor coding changes.
|
||||||
|
//
|
||||||
// Revision 1.17 2005/11/03 12:43:55 syntheticpp
|
// Revision 1.17 2005/11/03 12:43:55 syntheticpp
|
||||||
// more doxygen documentation, modules added
|
// more doxygen documentation, modules added
|
||||||
//
|
//
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue