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

📄 sbheap.c

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 C
📖 第 1 页 / 共 5 页
字号:
/***
*sbheap.c -  Small-block heap code
*
*       Copyright (c) 1996-1998, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Core code for small-block heap.
*
*******************************************************************************/

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <winheap.h>
#include <windows.h>

/***
 * Current (VC++ 6.0) small-block heap code and data
 ***/

size_t      __sbh_threshold;
int         __sbh_initialized;

PHEADER     __sbh_pHeaderList;          //  pointer to list start
PHEADER     __sbh_pHeaderScan;          //  pointer to list rover
int         __sbh_sizeHeaderList;       //  allocated size of list
int         __sbh_cntHeaderList;        //  count of entries defined

PHEADER     __sbh_pHeaderDefer;
int         __sbh_indGroupDefer;

/*
 * Prototypes for user functions.
 */
size_t __cdecl _get_sbh_threshold(void);
int    __cdecl _set_sbh_threshold(size_t);

void DumpEntry(char *, int *);

/***
*size_t _get_sbh_threshold() - return small-block threshold
*
*Purpose:
*       Return the current value of __sbh_threshold
*
*Entry:
*       None.
*
*Exit:
*       See above.
*
*Exceptions:
*
*******************************************************************************/

size_t __cdecl _get_sbh_threshold (void)
{
        if ( __active_heap == __V6_HEAP )
            return __sbh_threshold;
        else if ( __active_heap == __V5_HEAP )
            return __old_sbh_threshold;
        else
            return 0;
}

/***
*int _set_sbh_threshold(threshold) - set small-block heap threshold
*
*Purpose:
*       Set the upper limit for the size of an allocation which will be
*       supported from the small-block heap.
*
*Entry:
*       size_t threshold - proposed new value for __sbh_theshold
*
*Exit:
*       Returns 1 if successful. Returns 0 if threshold was too big.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl _set_sbh_threshold (size_t threshold)
{
        if ( __active_heap == __V6_HEAP )
        {
            //  test against maximum value - if too large, return error
            if ( threshold <= MAX_ALLOC_DATA_SIZE )
            {
                __sbh_threshold = threshold;
                return 1;
            }
            else
                return 0;
        }

        if ( __active_heap == __V5_HEAP )
        {
            //  Round up the proposed new value to the nearest paragraph
            threshold = (threshold + _OLD_PARASIZE - 1) & ~(_OLD_PARASIZE - 1);

            //  Require that at least two allocations be can be made within a
            //  page.
            if ( threshold <= (_OLD_PARASIZE * (_OLD_PARAS_PER_PAGE / 2)) ) {
                __old_sbh_threshold = threshold;
                return 1;
            }
            else
                return 0;
        }

        //  if necessary, initialize a small-block heap
        if ( (__active_heap == __SYSTEM_HEAP) && (threshold > 0) )
        {
            LinkerVersion lv;

            _GetLinkerVersion(&lv);
            if (lv.bverMajor >= 6)
            {
                //  Initialize the VC++ 6.0 small-block heap
                if ( (threshold <= MAX_ALLOC_DATA_SIZE) &&
                     __sbh_heap_init(threshold) )
                {
                    __sbh_threshold = threshold;
                    __active_heap = __V6_HEAP;
                    return 1;
                }
            }
            else
            {
                //  Initialize the old (VC++ 5.0) small-block heap
                threshold = (threshold + _OLD_PARASIZE - 1) &
                            ~(_OLD_PARASIZE - 1);
                if ( (threshold <= (_OLD_PARASIZE * (_OLD_PARAS_PER_PAGE / 2)))
                     && (__old_sbh_new_region() != NULL) )
                {
                    __old_sbh_threshold = threshold;
                    __active_heap = __V5_HEAP;
                    return 1;
                }
            }
        }

        return 0;
}

/***
*int __sbh_heap_init() - set small-block heap threshold
*
*Purpose:
*       Allocate space for initial header list and init variables.
*
*Entry:
*       None.
*
*Exit:
*       Returns 1 if successful. Returns 0 if initialization failed.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl __sbh_heap_init (size_t threshold)
{
        if (!(__sbh_pHeaderList = HeapAlloc(_crtheap, 0, 16 * sizeof(HEADER))))
            return FALSE;

        __sbh_threshold = threshold;
        __sbh_pHeaderScan = __sbh_pHeaderList;
        __sbh_pHeaderDefer = NULL;
        __sbh_cntHeaderList = 0;
        __sbh_sizeHeaderList = 16;

        return TRUE;
}

/***
*PHEADER *__sbh_find_block(pvAlloc) - find block in small-block heap
*
*Purpose:
*       Determine if the specified allocation block lies in the small-block
*       heap and, if so, return the header to be used for the block.
*
*Entry:
*       void * pvBlock - pointer to block to be freed
*
*Exit:
*       If successful, a pointer to the header to use is returned.
*       If unsuccessful, NULL is returned.
*
*Exceptions:
*
*******************************************************************************/

PHEADER __cdecl __sbh_find_block (void * pvAlloc)
{
        PHEADER         pHeaderLast = __sbh_pHeaderList + __sbh_cntHeaderList;
        PHEADER         pHeader;
        unsigned int    offRegion;

        //  scan through the header list to determine if entry
        //  is in the region heap data reserved address space
        pHeader = __sbh_pHeaderList;
        while (pHeader < pHeaderLast)
        {
            offRegion = (unsigned int)pvAlloc - (unsigned int)pHeader->pHeapData;
            if (offRegion < BYTES_PER_REGION)
                return pHeader;
            pHeader++;
        }
        return NULL;
}

#ifdef _DEBUG

/***
*int __sbh_verify_block(pHeader, pvAlloc) - verify pointer in sbh
*
*Purpose:
*       Test if pointer is valid within the heap header given.
*
*Entry:
*       pHeader - pointer to HEADER where entry should be
*       pvAlloc - pointer to test validity of
*
*Exit:
*       Returns 1 if pointer is valid, else 0.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl __sbh_verify_block (PHEADER pHeader, void * pvAlloc)
{
        unsigned int    indGroup;
        unsigned int    offRegion;

        //  calculate region offset to determine the group index
        offRegion = (unsigned int)pvAlloc - (unsigned int)pHeader->pHeapData;
        indGroup = offRegion / BYTES_PER_GROUP;

        //  return TRUE if:
        //      group is committed (bit in vector cleared) AND
        //      pointer is at paragraph boundary AND
        //      pointer is not at start of page
        return (!(pHeader->bitvCommit & (0x80000000UL >> indGroup))) &&
                (!(offRegion & 0xf)) &&
                (offRegion & (BYTES_PER_PAGE - 1));
}

#endif  /* _DEBUG */

/***
*void __sbh_free_block(preg, ppage, pmap) - free block
*
*Purpose:
*       Free the specified block from the small-block heap.
*
*Entry:
*       pHeader - pointer to HEADER of region to free memory
*       pvAlloc - pointer to memory to free
*
*Exit:
*       No return value.
*
*Exceptions:
*
*******************************************************************************/

void __cdecl __sbh_free_block (PHEADER pHeader, void * pvAlloc)
{
    PREGION         pRegion;
    PGROUP          pGroup;
    PENTRY          pHead;
    PENTRY          pEntry;
    PENTRY          pNext;
    PENTRY          pPrev;
    void *          pHeapDecommit;
    int             sizeEntry;
    int             sizeNext;
    int             sizePrev;
    unsigned int    indGroup;
    unsigned int    indEntry;
    unsigned int    indNext;
    unsigned int    indPrev;
    unsigned int    offRegion;

    //  region is determined by the header
    pRegion = pHeader->pRegion;

    //  use the region offset to determine the group index
    offRegion = (unsigned int)pvAlloc - (unsigned int)pHeader->pHeapData;
    indGroup = offRegion / BYTES_PER_GROUP;
    pGroup = &pRegion->grpHeadList[indGroup];

    //  get size of entry - decrement value since entry is allocated
    pEntry = (PENTRY)((char *)pvAlloc - sizeof(int));
    sizeEntry = pEntry->sizeFront - 1;

    //  check if the entry is already free. note the size has already been
    // decremented
    if ( (sizeEntry & 1 ) != 0 )
        return;

    //  point to next entry to get its size
    pNext = (PENTRY)((char *)pEntry + sizeEntry);
    sizeNext = pNext->sizeFront;

    //  get size from end of previous entry
    sizePrev = ((PENTRYEND)((char *)pEntry - sizeof(int)))->sizeBack;

    //  test if next entry is free by an even size value

    if ((sizeNext & 1) == 0)
    {
        //  free next entry - disconnect and add its size to sizeEntry

        //  determine index of next entry
        indNext = (sizeNext >> 4) - 1;
        if (indNext > 63)
            indNext = 63;

        //  test entry is sole member of bucket (next == prev),
        if (pNext->pEntryNext == pNext->pEntryPrev)
        {
            //  clear bit in group vector, decrement region count
            //  if region count is now zero, clear bit in header
            //  entry vector
            if (indNext < 32)
            {
                pRegion->bitvGroupHi[indGroup] &= ~(0x80000000L >> indNext);
                if (--pRegion->cntRegionSize[indNext] == 0)
                    pHeader->bitvEntryHi &= ~(0x80000000L >> indNext);
            }
            else
            {
                pRegion->bitvGroupLo[indGroup] &=
                                            ~(0x80000000L >> (indNext - 32));
                if (--pRegion->cntRegionSize[indNext] == 0)
                    pHeader->bitvEntryLo &= ~(0x80000000L >> (indNext - 32));
            }
        }

        //  unlink entry from list
        pNext->pEntryPrev->pEntryNext = pNext->pEntryNext;
        pNext->pEntryNext->pEntryPrev = pNext->pEntryPrev;

        //  add next entry size to freed entry size
        sizeEntry += sizeNext;
    }

    //  compute index of free entry (plus next entry if it was free)
    indEntry = (sizeEntry >> 4) - 1;
    if (indEntry > 63)
        indEntry = 63;

    //  test if previous entry is free by an even size value
    if ((sizePrev & 1) == 0)
    {
        //  free previous entry - add size to sizeEntry and
        //  disconnect if index changes

        //  get pointer to previous entry
        pPrev = (PENTRY)((char *)pEntry - sizePrev);

        //  determine index of previous entry
        indPrev = (sizePrev >> 4) - 1;
        if (indPrev > 63)
            indPrev = 63;

⌨️ 快捷键说明

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