⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smallobj.cpp

📁 Windows Mobile平台上使用GDI+。GDI+功能很强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        return true;    }    if ( IsFilled() )        // Useless to do further corruption checks if all blocks allocated.        return false;    unsigned char index = firstAvailableBlock_;    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;    /* 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;    /* The loop goes along singly linked-list of stealth indexes and makes sure     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 );        foundBlocks.set( index, true );        ++cc;        if ( cc >= blocksAvailable_ )            // Successfully counted off number of nodes in linked-list.            break;        index = *nextBlock;        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;        }        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;        }    }    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{    (void) numBlocks;        if ( IsFilled() )        return false;    unsigned char * place = static_cast< unsigned char * >( p );    // Alignment check    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;}// FixedAllocator::FixedAllocator ---------------------------------------------FixedAllocator::FixedAllocator()    : blockSize_( 0 )    , numBlocks_( 0 )    , chunks_( 0 )    , allocChunk_( NULL )    , deallocChunk_( NULL )    , emptyChunk_( NULL ){}// FixedAllocator::~FixedAllocator --------------------------------------------FixedAllocator::~FixedAllocator(){#ifdef DO_EXTRA_LOKI_TESTS    TrimEmptyChunk();    assert( chunks_.empty() && "Memory leak detected!" );#endif    for ( ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i )       i->Release();}// FixedAllocator::Initialize -------------------------------------------------void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize ){    assert( blockSize > 0 );    assert( pageSize >= blockSize );    blockSize_ = blockSize;    std::size_t numBlocks = pageSize / blockSize;    if ( numBlocks > MaxObjectsPerChunk_ ) numBlocks = MaxObjectsPerChunk_;    else if ( numBlocks < MinObjectsPerChunk_ ) numBlocks = MinObjectsPerChunk_;    numBlocks_ = static_cast<unsigned char>(numBlocks);    assert(numBlocks_ == numBlocks);}// FixedAllocator::CountEmptyChunks -------------------------------------------std::size_t FixedAllocator::CountEmptyChunks( void ) const{#ifdef DO_EXTRA_LOKI_TESTS    // This code is only used for specialized tests of the allocator.    // It is #ifdef-ed so that its O(C) complexity does not overwhelm the    // functions which call it.    std::size_t count = 0;    for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )    {        const Chunk & chunk = *it;        if ( chunk.HasAvailable( numBlocks_ ) )            ++count;    }    return count;#else    return ( NULL == emptyChunk_ ) ? 0 : 1;#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 ---------------------------------------------------const Chunk * FixedAllocator::HasBlock( void * p ) const{    const std::size_t chunkLength = numBlocks_ * blockSize_;    for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )    {        const Chunk & chunk = *it;        if ( chunk.HasBlock( p, chunkLength ) )            return &chunk;    }    return NULL;}// FixedAllocator::TrimEmptyChunk ---------------------------------------------bool FixedAllocator::TrimEmptyChunk( void ){    // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.    assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );    if ( NULL == emptyChunk_ ) return false;    // If emptyChunk_ points to valid Chunk, then chunk list is not empty.    assert( !chunks_.empty() );    // And there should be exactly 1 empty Chunk.    assert( 1 == CountEmptyChunks() );    Chunk * lastChunk = &chunks_.back();    if ( lastChunk != emptyChunk_ )        std::swap( *emptyChunk_, *lastChunk );    assert( lastChunk->HasAvailable( numBlocks_ ) );    lastChunk->Release();    chunks_.pop_back();    if ( chunks_.empty() )    {        allocChunk_ = NULL;        deallocChunk_ = NULL;    }    else    {        if ( deallocChunk_ == emptyChunk_ )        {            deallocChunk_ = &chunks_.front();            assert( deallocChunk_->blocksAvailable_ < numBlocks_ );        }        if ( allocChunk_ == emptyChunk_ )        {            allocChunk_ = &chunks_.back();            assert( allocChunk_->blocksAvailable_ < numBlocks_ );        }    }    emptyChunk_ = NULL;    assert( 0 == CountEmptyChunks() );    return true;}// FixedAllocator::TrimChunkList ----------------------------------------------bool FixedAllocator::TrimChunkList( void ){    if ( chunks_.empty() )    {        assert( NULL == allocChunk_ );        assert( NULL == deallocChunk_ );    }    if ( chunks_.size() == chunks_.capacity() )        return false;    // Use the "make-a-temp-and-swap" trick to remove excess capacity.    Chunks( chunks_ ).swap( chunks_ );    return true;}// FixedAllocator::MakeNewChunk -----------------------------------------------bool FixedAllocator::MakeNewChunk( void ){    bool allocated = false;    try    {        std::size_t size = chunks_.size();        // Calling chunks_.reserve *before* creating and initializing the new        // Chunk means that nothing is leaked by this function in case an        // exception is thrown from reserve.        if ( chunks_.capacity() == size )        {            if ( 0 == size ) size = 4;            chunks_.reserve( size * 2 );        }        Chunk newChunk;        allocated = newChunk.Init( blockSize_, numBlocks_ );        if ( allocated )            chunks_.push_back( newChunk );    }    catch ( ... )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -