📄 dbgheap.c
字号:
*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 nNewSize - requested size for the re-allocated block
* 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:
*
*******************************************************************************/
static void * __cdecl realloc_help(
void * pUserData,
size_t nNewSize,
int nBlockUse,
const char * szFileName,
int nLine,
int fRealloc
)
{
long lRequest;
int fIgnore = FALSE;
unsigned char *pUserBlock;
_CrtMemBlockHeader * pOldBlock;
_CrtMemBlockHeader * pNewBlock;
/*
* 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 (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)
_ASSERTE(_CrtCheckMemory());
lRequest = _lRequestCurr;
if (lRequest == _crtBreakAlloc)
_CrtDbgBreak(); /* break into debugger at specific memory leak */
/* forced failure */
if (!(*_pfnAllocHook)(_HOOK_REALLOC, pUserData, nNewSize, nBlockUse, lRequest, 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)UINT_MAX - nNoMansLandSize - sizeof(_CrtMemBlockHeader))
{
_RPT1(_CRT_ERROR, "Allocation too large or negative: %u bytes.\n",
nNewSize);
return NULL;
}
if (nBlockUse != _NORMAL_BLOCK
&& _BLOCK_TYPE(nBlockUse) != _CLIENT_BLOCK
&& _BLOCK_TYPE(nBlockUse) != _CRT_BLOCK)
{
_RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");
}
/*
* 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;
_ASSERTE(_BLOCK_TYPE(pOldBlock->nBlockUse)==_BLOCK_TYPE(nBlockUse));
}
/*
* note that all header values will remain valid
* and min(nNewSize,nOldSize) bytes of data will also remain valid
*/
if (fRealloc)
{
if (NULL == (pNewBlock = _realloc_base(pOldBlock,
sizeof(_CrtMemBlockHeader) + nNewSize + nNoMansLandSize)))
return NULL;
}
else {
if (NULL == (pNewBlock = _expand_base(pOldBlock,
sizeof(_CrtMemBlockHeader) + nNewSize + nNoMansLandSize)))
return NULL;
}
/* commit allocation */
++_lRequestCurr;
if (!fIgnore)
{
/* keep track of total amount of memory allocated */
_lTotalAlloc -= pNewBlock->nDataSize;
_lTotalAlloc += nNewSize;
_lCurAlloc -= pNewBlock->nDataSize;
_lCurAlloc += nNewSize;
if (_lCurAlloc > _lMaxAlloc)
_lMaxAlloc = _lCurAlloc;
}
pUserBlock = pbData(pNewBlock);
/* if the block grew, put in special value */
if (nNewSize > pNewBlock->nDataSize)
memset(pUserBlock + pNewBlock->nDataSize, _bCleanLandFill,
nNewSize - pNewBlock->nDataSize);
/* fill in gap after real block */
memset(pUserBlock + nNewSize, _bNoMansLandFill, nNoMansLandSize);
if (!fIgnore)
{
pNewBlock->szFileName = (char *)szFileName;
pNewBlock->nLine = nLine;
pNewBlock->lRequest = lRequest;
}
pNewBlock->nDataSize = nNewSize;
_ASSERTE(fRealloc || (!fRealloc && pNewBlock == pOldBlock));
/* if block did not move or ignored, we are done */
if (pNewBlock == pOldBlock || fIgnore)
return (void *)pUserBlock;
/* must remove old memory from dbg heap list */
/* note that new block header pointers still valid */
if (pNewBlock->pBlockHeaderNext)
{
pNewBlock->pBlockHeaderNext->pBlockHeaderPrev
= pNewBlock->pBlockHeaderPrev;
}
else
{
_ASSERTE(_pLastBlock == pOldBlock);
_pLastBlock = pNewBlock->pBlockHeaderPrev;
}
if (pNewBlock->pBlockHeaderPrev)
{
pNewBlock->pBlockHeaderPrev->pBlockHeaderNext
= pNewBlock->pBlockHeaderNext;
}
else
{
_ASSERTE(_pFirstBlock == pOldBlock);
_pFirstBlock = pNewBlock->pBlockHeaderNext;
}
/* put new memory into list */
if (_pFirstBlock)
_pFirstBlock->pBlockHeaderPrev = pNewBlock;
else
_pLastBlock = pNewBlock;
pNewBlock->pBlockHeaderNext = _pFirstBlock;
pNewBlock->pBlockHeaderPrev = NULL;
/* link blocks together */
_pFirstBlock = pNewBlock;
return (void *)pUserBlock;
}
/***
*void * realloc() - reallocate a block of memory in the heap
*
*Purpose:
* Re-allocates a block in the heap to nNewSize bytes. nNewSize 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.
*
* Re-allocates 'normal' memory block.
*
*Entry:
* void * pUserData - pointer to previously allocated block
* size_t nNewSize - requested size for the re-allocated block
*
*Exit:
* Success: Pointer to (user portion of) memory block
* Failure: NULL
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP void * __cdecl realloc(
void * pUserData,
size_t nNewSize
)
{
void *res = _realloc_dbg(pUserData, nNewSize, _NORMAL_BLOCK, NULL, 0);
return res;
}
/***
*void * _realloc_dbg() - reallocate a block of memory in the heap
* - with info
*
*Purpose:
* Re-allocates a block in the heap to nNewSize bytes. nNewSize 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.
*
* Re-allocates any type of supported memory block.
*
*Entry:
* void * pUserData - pointer previously allocated block
* size_t nNewSize - requested size for the re-allocated block
* int nBlockUse - block type
* char * szFileName - file name
* int nLine - line number
*
*Exit:
* Success: Pointer to (user portion of) memory block
* Failure: NULL
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP void * __cdecl _realloc_dbg(
void * pUserData,
size_t nNewSize,
int nBlockUse,
const char * szFileName,
int nLine
)
{
void * pvBlk;
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
/* allocate the block
*/
pvBlk = realloc_help(pUserData,
nNewSize,
nBlockUse,
szFileName,
nLine,
TRUE);
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
return pvBlk;
}
/***
*void * _expand() - 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.
*
* Re-allocates 'normal' memory block.
*
*Entry:
* void * pUserData - pointer to block in the heap previously allocated
* by a call to malloc(), realloc() or _expand().
*
* size_t nNewSize - requested size for the resized block
*
*Exit:
* Success: Pointer to the resized memory block (i.e., pUserData)
* Failure: NULL
*
*Uses:
*
*Exceptions:
* If pUserData does not point to a valid allocation block in the heap,
* _expand() will behave unpredictably and probably corrupt the heap.
*
*******************************************************************************/
_CRTIMP void * __cdecl _expand(
void * pUserData,
size_t nNewSize
)
{
void *res = _expand_dbg(pUserData, nNewSize, _NORMAL_BLOCK, NULL, 0);
return res;
}
/***
*void * _expand() - 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.
*
* Re-allocates any type of supported memory block.
*
*Entry:
* void * pUserData - pointer to block in the heap previously allocated
* by a call to malloc(), realloc() or _expand().
*
* size_t nNewSize - requested size for the resized block
*
*Exit:
* Success: Pointer to the resized memory block (i.e., pUserData)
* Failure: NULL
*
*Uses:
*
*Exceptions:
* If pUserData does not point to a valid allocation block in the heap,
* _expand() will behave unpredictably and probably corrupt the heap.
*
*******************************************************************************/
_CRTIMP void * __cdecl _expand_dbg(
void * pUserData,
size_t nNewSize,
int nBlockUse,
const char * szFileName,
int nLine
)
{
void * pvBlk;
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
/* allocate the block
*/
pvBlk = realloc_help(pUserData,
nNewSize,
nBlockUse,
szFileName,
nLine,
FALSE);
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
return pvBlk;
}
/***
*void free() - free a block in the debug heap
*
*Purpose:
* Frees a 'normal' memory block.
*
*Entry:
* void * pUserData - pointer to a (user portion) of memory block in the
* debug heap
*
*Return:
* <void>
*
*******************************************************************************/
_CRTIMP void __cdecl free(
void * pUserData
)
{
_free_dbg(pUserData, _NORMAL_BLOCK);
}
#ifdef _MT
void __cdecl _free_lk(
void * pUserData
)
{
_free_dbg_lk(pUserData, _NORMAL_BLOCK);
}
#endif /* _MT */
/***
*void _free_dbg() - free a block in the debug heap
*
*Purpose:
* Frees any type of supported block.
*
*Entry:
* void * pUserData - pointer to a (user portion) of memory block in the
* debug heap
* int nBlockUse - block type
*
*Return:
* <void>
*
*******************************************************************************/
#ifdef _MT
_CRTIMP void __cdecl _free_dbg(
void * pUserData,
int nBlockUse
)
{
/* lock the heap
*/
_mlock(_HEAP_LOCK);
__try {
/* allocate the block
*/
_free_dbg_lk(pUserData, nBlockUse);
}
__finally {
/* unlock the heap
*/
_munlock(_HEAP_LOCK);
}
}
void __cdecl _free_dbg_lk(
#else /* _MT */
_CRTIMP void __cdecl _free_dbg(
#endif /* _MT */
void * pUserData,
int nBlockUse
)
{
_CrtMemBlockHeader * pHead;
/* verify heap before freeing */
if (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)
_ASSERTE(_CrtCheckMemory());
if (pUserData == NULL)
return;
/* forced failure */
if (!(*_pfnAllocHook)(_HOOK_FREE, pUserData, 0, nBlockUse, 0L, NULL, 0))
{
_RPT0(_CRT_WARN, "Client hook free failure.\n");
return;
}
/*
* 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 */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -