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

📄 realloc.c

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 C
📖 第 1 页 / 共 2 页
字号:
*       Special Notes For Multi-thread: The heap is locked immediately prior
*       to assigning pdesc. This is after special cases (1) and (2), listed
*       above, are taken care of. The lock is released immediately prior to
*       the final return statement.
*
*Entry:
*       void *pblock - pointer to block in the heap previously allocated
*                 by a call to malloc(), realloc() or _expand().
*
*       size_t newsize  - requested size for the re-allocated block
*
*Exit:
*       Success:  Pointer to the re-allocated memory block
*       Failure:  NULL
*
*Uses:
*
*Exceptions:
*       If pblock does not point to a valid allocation block in the heap,
*       realloc() will behave unpredictably and probably corrupt the heap.
*
*******************************************************************************/

void * __cdecl _realloc_base (
        REG1 void *pblock,
        size_t newsize
        )
{
        REG2 _PBLKDESC pdesc;
        _PBLKDESC pdesc2;
        void *retp;
        size_t oldsize;
        size_t currsize;

        /* special cases, handling mandated by ANSI
         */
        if ( pblock == NULL )
            /* just do a malloc of newsize bytes and return a pointer to
             * the new block
              */
            return( _malloc_base(newsize) );

        if ( newsize == 0 ) {
            /* free the block and return NULL
             */
            _free_base(pblock);
            return( NULL );
        }

        /* make newsize a valid allocation block size (i.e., round up to the
         * nearest whole number of dwords)
         */
        newsize = _ROUND2(newsize, _GRANULARITY);


        /* if multi-thread support enabled, lock the heap here
         */
        _mlock(_HEAP_LOCK);

        /* set pdesc to point to the descriptor for *pblock
         */
        pdesc = _BACKPTR(pblock);

        if ( _ADDRESS(pdesc) != ((char *)pblock - _HDRSIZE) )
            _heap_abort();

        /* see if pblock is big enough already, or can be expanded (in place)
         * to be big enough.
         */
        if ( ((oldsize = currsize = BLKSZ(pdesc, pblock)) > newsize) ||
             (_heap_expand_block(pdesc, &currsize, newsize) == 0) ) {

            /* if necessary, mark pdesc as inuse
             */
            if ( _IS_FREE(pdesc) ) {
                _SET_INUSE(pdesc);
            }

            /* trim pdesc down to be exactly newsize bytes, if necessary
             */
            if ( (currsize > newsize) &&
                 ((pdesc2 = _heap_split_block(pdesc, newsize)) != NULL) )
            {
                _SET_FREE(pdesc2);
            }

            retp = pblock;
            goto realloc_done;
        }

        /* try malloc-ing a new block of the requested size. if successful,
         * copy over the data from the original block and free it.
         */
        if ( (retp = _malloc_base(newsize)) != NULL ) {
            memcpy(retp, pblock, oldsize);
            _free_base_lk(pblock);
        }
        /* else if unsuccessful, return retp (== NULL) */

realloc_done:
        /* if multi-thread support is enabled, unlock the heap here
         */
        _munlock(_HEAP_LOCK);

        return(retp);
}


/***
*void *_expand(void *pblock, size_t newsize) - expand/contract a block of memory
*       in the heap
*
*Purpose:
*       Resizes a block in the heap to newsize bytes. newsize may be either
*       greater (expansion) or less (contraction) than the original size of
*       the block. The block is NOT moved. In the case of expansion, if the
*       block cannot be expanded to newsize bytes, it is expanded as much as
*       possible.
*
*       Special Notes For Multi-thread: The heap is locked just before pdesc
*       is assigned and unlocked immediately prior to the return statement.
*
*Entry:
*       void *pblock - pointer to block in the heap previously allocated
*                 by a call to malloc(), realloc() or _expand().
*
*       size_t newsize  - requested size for the resized block
*
*Exit:
*       Success:  Pointer to the resized memory block (i.e., pblock)
*       Failure:  NULL
*
*Uses:
*
*Exceptions:
*       If pblock does not point to a valid allocation block in the heap,
*       _expand() will behave unpredictably and probably corrupt the heap.
*
*******************************************************************************/

void * __cdecl _expand_base (
        REG1 void *pblock,
        size_t newsize
        )
{
        REG2 _PBLKDESC pdesc;
        _PBLKDESC pdesc2;
        void *retp;
        size_t oldsize;
        size_t currsize;
        int index;
#if defined (_M_MPPC) || defined (_M_M68K)
        struct _heap_region_ *pHeapRegions;
#endif  /* defined (_M_MPPC) || defined (_M_M68K) */

        /* make newsize a valid allocation block size (i.e., round up to the
         * nearest whole number of dwords)
         */
        newsize = _ROUND2(newsize, _GRANULARITY);


        retp = pblock;

        /* validate size */
        if ( newsize > _HEAP_MAXREQ )
            newsize = _HEAP_MAXREQ;

        /* if multi-thread support enabled, lock the heap here
         */
        _mlock(_HEAP_LOCK);

        /* set pdesc to point to the descriptor for *pblock
         */
        pdesc = _BACKPTR(pblock);

        /* see if pblock is big enough already, or can be expanded (in place)
         * to be big enough.
         */
        if ( ((oldsize = currsize = BLKSZ(pdesc, pblock)) >= newsize) ||
             (_heap_expand_block(pdesc, &currsize, newsize) == 0) ) {
            /* pblock is (now) big enough. trim it down, if necessary
             */
            if ( (currsize > newsize) &&
                 ((pdesc2 = _heap_split_block(pdesc, newsize)) != NULL) )
            {
                _SET_FREE(pdesc2);
                currsize = newsize;
            }
            goto expand_done;
        }

        /* if the heap block is at the end of a region, attempt to grow the
         * region
         */
        if ( (pdesc->pnextdesc == &_heap_desc.sentinel) ||
             _IS_DUMMY(pdesc->pnextdesc) ) {

            /* look up the region index
             */
#if defined (_M_MPPC) || defined (_M_M68K)
            pHeapRegions = (struct _heap_region_ *)(*hHeapRegions);
            for ( index = 0 ; index < _heap_region_table_cur ; index++ )
                if (((pHeapRegions + index)->_regbase < pblock) &&
                (((char *)((pHeapRegions + index)->_regbase) +
                (pHeapRegions + index)->_currsize) >= (char *)pblock) )
                    break;
#else  /* defined (_M_MPPC) || defined (_M_M68K) */
            for ( index = 0 ; index < _HEAP_REGIONMAX ; index++ )
                if ( (_heap_regions[index]._regbase < pblock) &&
                     (((char *)(_heap_regions[index]._regbase) +
                       _heap_regions[index]._currsize) >=
                     (char *)pblock) )
                    break;
#endif  /* defined (_M_MPPC) || defined (_M_M68K) */
            /* make sure a valid region index was obtained (pblock could
             * lie in a portion of heap memory donated by a user call to
             * _heapadd(), which therefore would not appear in the region
             * table)
             */
#if defined (_M_MPPC) || defined (_M_M68K)
            if ( index == _heap_region_table_cur ) {
#else  /* defined (_M_MPPC) || defined (_M_M68K) */
            if ( index == _HEAP_REGIONMAX ) {
#endif  /* defined (_M_MPPC) || defined (_M_M68K) */
                retp = NULL;
                goto expand_done;
            }

            /* try growing the region. the difference between newsize and
             * the current size of the block, rounded up to the nearest
             * whole number of pages, is the amount the region needs to
             * be grown. if successful, try expanding the block again
             */
            if ( (_heap_grow_region(index, _ROUND2(newsize - currsize,
                  _PAGESIZE_)) == 0) &&
                 (_heap_expand_block(pdesc, &currsize, newsize) == 0) )
            {
                /* pblock is (now) big enough. trim it down to be
                 * exactly size bytes, if necessary
                 */
                if ( (currsize > newsize) && ((pdesc2 =
                       _heap_split_block(pdesc, newsize)) != NULL) )
                {
                    _SET_FREE(pdesc2);
                    currsize = newsize;
                }
            }
            else
                retp = NULL;
        }
        else
            retp = NULL;

expand_done:
        /* if multi-thread support is enabled, unlock the heap here
         */
        _munlock(_HEAP_LOCK);

        return(retp);
}


/***
*int _heap_expand_block(pdesc, pcurrsize, newsize) - expand an allocation block
*       in place (without trying to 'grow' the heap)
*
*Purpose:
*
*Entry:
*       _PBLKDESC pdesc   - pointer to the allocation block descriptor
*       size_t *pcurrsize - pointer to size of the allocation block (i.e.,
*                   *pcurrsize == _BLKSIZE(pdesc), on entry)
*       size_t newsize    - requested minimum size for the expanded allocation
*                   block (i.e., newsize >= _BLKSIZE(pdesc), on exit)
*
*Exit:
*       Success:  0
*       Failure: -1
*       In either case, *pcurrsize is updated with the new size of the block
*
*Exceptions:
*       It is assumed that pdesc points to a valid allocation block descriptor.
*       It is also assumed that _BLKSIZE(pdesc) == *pcurrsize on entry. If
*       either of these assumptions is violated, _heap_expand_block will almost
*       certainly trash the heap.
*
*******************************************************************************/

static int __cdecl _heap_expand_block (
        REG1 _PBLKDESC pdesc,
        REG3 size_t *pcurrsize,
        size_t newsize
        )
{
        REG2 _PBLKDESC pdesc2;

        _ASSERTE(("_heap_expand_block: bad pdesc arg", _CHECK_PDESC(pdesc)));
        _ASSERTE(("_heap_expand_block: bad pcurrsize arg", *pcurrsize == _BLKSIZE(pdesc)));

        for ( pdesc2 = pdesc->pnextdesc ; _IS_FREE(pdesc2) ;
              pdesc2 = pdesc->pnextdesc ) {

            /* coalesce with pdesc. check for special case of pdesc2
             * being proverdesc.
             */
            pdesc->pnextdesc = pdesc2->pnextdesc;

            if ( pdesc2 == _heap_desc.proverdesc )
                _heap_desc.proverdesc = pdesc;

            /* update *pcurrsize, place *pdesc2 on the empty descriptor
             * list and see if the coalesced block is now big enough
             */
            *pcurrsize += _MEMSIZE(pdesc2);

            _PUTEMPTY(pdesc2)
        }

        if ( *pcurrsize >= newsize )
            return(0);
        else
            return(-1);
}


#endif  /* WINHEAP */

⌨️ 快捷键说明

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