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

📄 realloc.c

📁 C标准库源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***
*realloc.c - Reallocate a block of memory in the heap
*
*       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Defines the realloc() and _expand() functions.
*
*******************************************************************************/

#ifdef WINHEAP

#include <cruntime.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <winheap.h>
#include <windows.h>
#include <internal.h>
#include <mtdll.h>
#include <dbgint.h>


/***
*void *realloc(pblock, newsize) - reallocate a block of memory in the heap
*
*Purpose:
*       Reallocates a block in the heap to newsize bytes. newsize may be
*       either greater or less than the original size of the block. The
*       reallocation may result in moving the block as well as changing
*       the size. If the block is moved, the contents of the original block
*       are copied over.
*
*       Special ANSI Requirements:
*
*       (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
*
*       (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
*           NULL is returned)
*
*       (3) if the realloc() fails, the object pointed to by pblock is left
*           unchanged
*
*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 (void * pBlock, size_t newsize)
{
    PHEADER     pHeader;
    void *      pvReturn;
    size_t      oldsize;

    //  if ptr is NULL, call malloc
    if (pBlock == NULL)
        return(_malloc_base(newsize));

    //  if ptr is nonNULL and size is zero, call free and return NULL
    if (newsize == 0)
    {
        _free_base(pBlock);
        return(NULL);
    }


    for (;;) {

        pvReturn = NULL;
        if (newsize <= _HEAP_MAXREQ)
        {
            _mlock(_HEAP_LOCK);

            //  test if current block is in the small-block heap
            if ((pHeader = __sbh_find_block(pBlock)) != NULL)
            {
                //  if the new size is not over __sbh_threshold, attempt
                //  to reallocate within the small-block heap
                if (newsize <= __sbh_threshold)
                {
                    if (__sbh_resize_block(pHeader, pBlock, newsize))
                        pvReturn = pBlock;
                    else if ((pvReturn = __sbh_alloc_block(newsize)) != NULL)
                    {
                        oldsize = ((PENTRY)((char *)pBlock -
                                            sizeof(int)))->sizeFront - 1;
                        memcpy(pvReturn, pBlock, __min(oldsize, newsize));
                        __sbh_free_block(pHeader, pBlock);
                    }
                }

                //  If the reallocation has not been (successfully)
                //  performed in the small-block heap, try to allocate
                //  a new block with HeapAlloc.
                if (pvReturn == NULL)
                {
                    if (newsize == 0)
                        newsize = 1;
                    newsize = (newsize + BYTES_PER_PARA - 1) &
                                       ~(BYTES_PER_PARA - 1);
                    if ((pvReturn = HeapAlloc(_crtheap, 0, newsize)) != NULL)
                    {
                        oldsize = ((PENTRY)((char *)pBlock -
                                                sizeof(int)))->sizeFront - 1;
                        memcpy(pvReturn, pBlock, __min(oldsize, newsize));
                        __sbh_free_block(pHeader, pBlock);
                    }
                }
                _munlock(_HEAP_LOCK);
            }
            else
            {
                _munlock(_HEAP_LOCK);
                if (newsize == 0)
                    newsize = 1;
                newsize = (newsize + BYTES_PER_PARA - 1) &
                                   ~(BYTES_PER_PARA - 1);
                pvReturn = HeapReAlloc(_crtheap, 0, pBlock, newsize);
            }
        }

        if ( pvReturn || _newmode == 0)
            return pvReturn;

        //  call installed new handler
        if (!_callnewh(newsize))
            return NULL;

        //  new handler was successful -- try to allocate again
    }
}

#else  /* WINHEAP */


#include <cruntime.h>
#include <heap.h>
#include <malloc.h>
#include <mtdll.h>
#include <stddef.h>
#include <string.h>
#include <dbgint.h>

#if defined (_M_MPPC) || defined (_M_M68K)
#include <macos\memory.h>       // Mac OS interface header
#endif  /* defined (_M_MPPC) || defined (_M_M68K) */

/* useful macro to compute the size of an allocation block given both a
 * pointer to the descriptor and a pointer to the user area of the block
 * (more efficient variant of _BLKSIZE macro, given the extra information)
 */
#define BLKSZ(pdesc_m,pblock_m)   ((unsigned)_ADDRESS((pdesc_m)->pnextdesc) - \
                    (unsigned)(pblock_m))

/* expand an allocation block, in place, up to or beyond a specified size
 * by coalescing it with subsequent free blocks (if possible)
 */
static int __cdecl _heap_expand_block(_PBLKDESC, size_t *, size_t);

#if defined (_M_MPPC) || defined (_M_M68K)
extern Handle hHeapRegions;
extern int _heap_region_table_cur;
#endif  /* defined (_M_MPPC) || defined (_M_M68K) */

/***
*void *realloc(void *pblock, size_t newsize) - reallocate a block of memory in
*       the heap
*
*Purpose:
*       Re-allocates a block in the heap to newsize bytes. newsize may be
*       either greater or less than the original size of the block. The
*       re-allocation may result in moving the block as well as changing
*       the size. If the block is moved, the contents of the original block
*       are copied over.
*
*       Special ANSI Requirements:
*
*       (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
*
*       (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
*           NULL is returned)
*
*       (3) if the realloc() fails, the object pointed to by pblock is left
*           unchanged
*
*       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();

⌨️ 快捷键说明

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