dbgheap.c

来自「C语言库函数的原型,有用的拿去」· C语言 代码 · 共 2,046 行 · 第 1/5 页

C
2,046
字号
                /* Diagnostic memory allocation from this point on */

                if (nSize > (size_t)(_HEAP_MAXREQ - nNoMansLandSize - sizeof(_CrtMemBlockHeader)))
                {
                    _RPT1(_CRT_ERROR, "Invalid allocation size: %Iu bytes.\n", nSize);
                    if (errno_tmp)
                    {
                        *errno_tmp = ENOMEM;
                    }
                }
                else
                {
                    if (!_BLOCK_TYPE_IS_VALID(nBlockUse))
                    {
                        _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
                    }

                    blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;

                    RTCCALLBACK(_RTC_FuncCheckSet_hook,(0));
                    pHead = (_CrtMemBlockHeader *)_heap_alloc_base(blockSize);

                    if (pHead == NULL)
                    {
                        if (errno_tmp)
                        {
                            *errno_tmp = ENOMEM;
                        }
                        RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));
                    }
                    else
                    {

                        /* commit allocation */
                        ++_lRequestCurr;

                        if (fIgnore)
                        {
                            pHead->pBlockHeaderNext = NULL;
                            pHead->pBlockHeaderPrev = NULL;
                            pHead->szFileName = NULL;
                            pHead->nLine = IGNORE_LINE;
                            pHead->nDataSize = nSize;
                            pHead->nBlockUse = _IGNORE_BLOCK;
                            pHead->lRequest = IGNORE_REQ;
                        }
                        else {
                            /* keep track of total amount of memory allocated */
                            if (SIZE_MAX - _lTotalAlloc > nSize)
                            {
                                _lTotalAlloc += nSize;
                            }
                            else
                            {
                                _lTotalAlloc = SIZE_MAX;
                            }
                            _lCurAlloc += nSize;

                            if (_lCurAlloc > _lMaxAlloc)
                            _lMaxAlloc = _lCurAlloc;

                            if (_pFirstBlock)
                                _pFirstBlock->pBlockHeaderPrev = pHead;
                            else
                                _pLastBlock = pHead;

                            pHead->pBlockHeaderNext = _pFirstBlock;
                            pHead->pBlockHeaderPrev = NULL;
                            pHead->szFileName = (char *)szFileName;
                            pHead->nLine = nLine;
                            pHead->nDataSize = nSize;
                            pHead->nBlockUse = nBlockUse;
                            pHead->lRequest = lRequest;

                            /* link blocks together */
                            _pFirstBlock = pHead;
                        }

                        /* fill in gap before and after real block */
                        memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize);
                        memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize);

                        /* fill data with silly value (but non-zero) */
                        memset((void *)pbData(pHead), _bCleanLandFill, nSize);

                        RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));

                        retval=(void *)pbData(pHead);
                    }
                }
            }

        }
        __finally {
            /* unlock the heap
             */
            _munlock(_HEAP_LOCK);
        }

        return retval;
}

/***
*void * _heap_alloc_dbg() - does actual allocation
*
*Purpose:
*       Does heap allocation.
*
*       Allocates any type of supported memory block.
*
*Entry:
*       size_t          nSize       - size of block requested
*       int             nBlockUse   - block type
*       char *          szFileName  - file name
*       int             nLine       - line number
*
*Exit:
*       Success:  Pointer to (user portion of) memory block
*       Failure:  NULL
*
*Exceptions:
*
*******************************************************************************/

extern "C" void * __cdecl _heap_alloc_dbg(
        size_t nSize,
        int nBlockUse,
        const char * szFileName,
        int nLine
        )
{
        int errno_tmp = 0;
        void * retval = _heap_alloc_dbg_impl(nSize, nBlockUse, szFileName, nLine, &errno_tmp);

        if ( retval == NULL && errno_tmp != 0 && _errno())
        {
            errno = errno_tmp; // recall, #define errno *_errno()
        }
        return retval;
}

/***
*void * _calloc_dbg_impl() - Get a block of memory from the debug heap, init to 0
*                    - with info
*
*Purpose:
*       Allocate of block of memory of at least size bytes from the debug
*       heap and return a pointer to it.
*
*       Allocates any type of supported memory block.
*
*Entry:
*       size_t          nNum        - number of elements in the array
*       size_t          nSize       - size of each element
*       int             nBlockUse   - block type
*       char *          szFileName  - file name
*       int             nLine       - line number
*       int  *          errno_tmp   - pointer of the temporary errno
*
*Exit:
*       Success:  Pointer to (user portion of) memory block
*       Failure:  NULL
*
*Exceptions:
*
*******************************************************************************/

extern "C" void * __cdecl _calloc_dbg_impl(
        size_t nNum,
        size_t nSize,
        int nBlockUse,
        const char * szFileName,
        int nLine,
        int * errno_tmp
        )
{
        void * pvBlk;

        /* ensure that (nSize * nNum) does not overflow */
        if (nNum > 0)
        {
            _VALIDATE_RETURN_NOEXC((_HEAP_MAXREQ / nNum) >= nSize, ENOMEM, NULL);
        }

        nSize *= nNum;

        /*
         * try to malloc the requested space
         */

        pvBlk = _nh_malloc_dbg_impl(nSize, _newmode, nBlockUse, szFileName, nLine, errno_tmp);

        /*
         * If malloc() succeeded, initialize the allocated space to zeros.
         * Note that unlike _calloc_base, exactly nNum bytes are set to zero.
         */

        if ( pvBlk != NULL )
        {
            memset(pvBlk, 0, nSize);
        }

        RTCCALLBACK(_RTC_Allocate_hook, (pvBlk, nSize, 0));

        return(pvBlk);
}

/***
*void * _calloc_dbg() - Get a block of memory from the debug heap, init to 0
*                    - with info
*
*Purpose:
*       Allocate of block of memory of at least size bytes from the debug
*       heap and return a pointer to it.
*
*       Allocates any type of supported memory block.
*
*Entry:
*       size_t          nNum        - number of elements in the array
*       size_t          nSize       - size of each element
*       int             nBlockUse   - block type
*       char *          szFileName  - file name
*       int             nLine       - line number
*
*Exit:
*       Success:  Pointer to (user portion of) memory block
*       Failure:  NULL
*
*Exceptions:
*
*******************************************************************************/

extern "C" _CRTIMP void * __cdecl _calloc_dbg(
        size_t nNum,
        size_t nSize,
        int nBlockUse,
        const char * szFileName,
        int nLine
        )
{
        int errno_tmp = 0;
        void * pvBlk = _calloc_dbg_impl(nNum, nSize, nBlockUse, szFileName, nLine, &errno_tmp);

        if ( pvBlk == NULL && errno_tmp != 0 && _errno())
        {
            errno = errno_tmp; // recall, #define errno *_errno()
        }
        return pvBlk;
}

/***
*static void * realloc_help() - does all the work for _realloc and _expand
*
*Purpose:
*       Helper function for _realloc and _expand.
*
*Entry:
*       void *          pUserData   - pointer previously allocated block
*       size_t *        pnNewSize   - requested size for the re-allocated block
*                                     changed to actual size during call
*       int             nBlockUse   - block type
*       char *          szFileName  - file name
*       int             nLine       - line number
*       int             fRealloc    - TRUE when _realloc, FALSE when _expand
*
*Exit:
*       Success:  Pointer to (user portion of) memory block
*       Failure:  NULL
*
*Exceptions:
*
*******************************************************************************/

extern "C" static void * __cdecl realloc_help(
        void * pUserData,
        size_t * pnNewSize,
        int nBlockUse,
        const char * szFileName,
        int nLine,
        int fRealloc
        )
{
        long lRequest;
        int fIgnore = FALSE;
        unsigned char *pUserBlock;
        _CrtMemBlockHeader * pOldBlock;
        _CrtMemBlockHeader * pNewBlock;
        size_t nNewSize = *pnNewSize;

        /*
         * ANSI: realloc(NULL, newsize) is equivalent to malloc(newsize)
         */
        if (pUserData == NULL)
        {
            return _malloc_dbg(nNewSize, nBlockUse, szFileName, nLine);
        }

        /*
         * ANSI: realloc(pUserData, 0) is equivalent to free(pUserData)
         * (except that NULL is returned)
         */
        if (fRealloc && nNewSize == 0)
        {
            _free_dbg(pUserData, nBlockUse);
            return NULL;
        }

        /* verify heap before re-allocation */
        if (check_frequency > 0)
            if (check_counter == (check_frequency - 1))
            {
                _ASSERTE(_CrtCheckMemory());
                check_counter = 0;
            }
            else
                check_counter++;

        lRequest = _lRequestCurr;

        if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)
            _CrtDbgBreak(); /* break into debugger at specific memory leak */

        /* forced failure */
        if ((_pfnAllocHook) && !(*_pfnAllocHook)(_HOOK_REALLOC, pUserData, nNewSize, nBlockUse, lRequest, (const unsigned char *)szFileName, nLine))
        {
            if (szFileName)
                _RPT2(_CRT_WARN, "Client hook re-allocation failure at file %hs line %d.\n",
                    szFileName, nLine);
            else
                _RPT0(_CRT_WARN, "Client hook re-allocation failure.\n");

            return NULL;
        }

        /* Diagnostic memory allocation from this point on */

        if (nNewSize > (size_t)(_HEAP_MAXREQ - nNoMansLandSize - sizeof(_CrtMemBlockHeader)))
        {
            if (szFileName)
            {
                _RPT3(_CRT_ERROR,
                    "Invalid allocation size: %Iu bytes.\n" _ALLOCATION_FILE_LINENUM,
                    nNewSize, szFileName, nLine);
            }
            else
            {
                _RPT1(_CRT_ERROR, "Invalid allocation size: %Iu bytes.\n", nNewSize);
            }
            errno = ENOMEM;
            return NULL;
        }

        if (nBlockUse != _NORMAL_BLOCK
            && _BLOCK_TYPE(nBlockUse) != _CLIENT_BLOCK
            && _BLOCK_TYPE(nBlockUse) != _CRT_BLOCK)
        {
            if (szFileName)
            {
                _RPT2(_CRT_ERROR,
                    "Error: memory allocation: bad memory block type.\n" _ALLOCATION_FILE_LINENUM,
                    szFileName, nLine);
            }
            else
            {
                _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
            }
        } else
        {
            if ( CheckBytes((unsigned char*)((uintptr_t)pUserData & ~(sizeof(uintptr_t) -1)) -nAlignGapSize,_bAlignLandFill, nAlignGapSize))
            {
                // We don't know (yet) where (file, linenum) pUserData was allocated
                _RPT1(_CRT_ERROR, "The Block at 0x%p was allocated by aligned routines, use _aligned_realloc()", pUserData);
                errno = EINVAL;
                return NULL;
            }
        }

        /*
         * If this ASSERT fails, a bad pointer has been passed in. It may be
         * totally bogus, or it may have been allocated from another heap.
         * The pointer MUST come from the 'local' heap.
         */
        _ASSERTE(_CrtIsValidHeapPointer(pUserData));

        /* get a pointer to memory block header */
        pOldBlock = pHdr(pUserData);

        if (pOldBlock->nBlockUse == _IGNORE_BLOCK)
            fIgnore = TRUE;

        if (fIgnore)
        {
            _ASSERTE(pOldBlock->nLine == IGNORE_LINE && pOldBlock->lRequest == IGNORE_REQ);
        }
        else {
            /* Error if freeing incorrect memory type */
            /* CRT blocks can be treated as NORMAL blocks */
            if (_BLOCK_TYPE(pOldBlock->nBlockUse) == _CRT_BLOCK && _BLOCK_TYPE(nBlockUse) == _NORMAL_BLOCK)
                nBlockUse = _CRT_BLOCK;
/* The following assertion was prone to false positives - JWM                      */
/*            _ASSERTE(_BLOCK_TYPE(pOldBlock->nBlockUse)==_BLOCK_TYPE(nBlockUse)); */

            /* checking the size of previous block */
            if (_lTotalAlloc < pOldBlock->nDataSize)
            {
                _RPT1(_CRT_ERROR, "Error: possible heap corruption at or near 0x%p", pUserData);
                errno = EINVAL;
                return NULL;
            }
        }

⌨️ 快捷键说明

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