📄 dbgheap.c
字号:
/* if we didn't already check entire heap, at least check this object */
if (!(_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF))
{
/* check no-mans-land gaps */
if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: before %hs block (#%d) at 0x%08X.\n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
(BYTE *) pbData(pHead));
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%08X.\n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
(BYTE *) pbData(pHead));
}
if (pHead->nBlockUse == _IGNORE_BLOCK)
{
_ASSERTE(pHead->nLine == IGNORE_LINE && pHead->lRequest == IGNORE_REQ);
/* fill the entire block including header with dead-land-fill */
memset(pHead, _bDeadLandFill,
sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
_free_base(pHead);
return;
}
/* CRT blocks can be freed as NORMAL blocks */
if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
nBlockUse = _CRT_BLOCK;
/* Error if freeing incorrect memory type */
_ASSERTE(pHead->nBlockUse == nBlockUse);
/* keep track of total amount of memory allocated */
_lCurAlloc -= pHead->nDataSize;
/* optionally reclaim memory */
if (!(_crtDbgFlag & _CRTDBG_DELAY_FREE_MEM_DF))
{
/* remove from the linked list */
if (pHead->pBlockHeaderNext)
{
pHead->pBlockHeaderNext->pBlockHeaderPrev = pHead->pBlockHeaderPrev;
}
else
{
_ASSERTE(_pLastBlock == pHead);
_pLastBlock = pHead->pBlockHeaderPrev;
}
if (pHead->pBlockHeaderPrev)
{
pHead->pBlockHeaderPrev->pBlockHeaderNext = pHead->pBlockHeaderNext;
}
else
{
_ASSERTE(_pFirstBlock == pHead);
_pFirstBlock = pHead->pBlockHeaderNext;
}
/* fill the entire block including header with dead-land-fill */
memset(pHead, _bDeadLandFill,
sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
_free_base(pHead);
}
else
{
pHead->nBlockUse = _FREE_BLOCK;
/* keep memory around as dead space */
memset(pbData(pHead), _bDeadLandFill, pHead->nDataSize);
}
}
/***
*size_t _msize() - calculate the size of specified block in the heap
*
*Purpose:
* Calculates the size of memory block (in the heap) pointed to by
* pUserData.
*
* For 'normal' memory block.
*
*Entry:
* void * pUserData - pointer to a memory block in the heap
*
*Return:
* size of the block
*
*******************************************************************************/
_CRTIMP size_t __cdecl _msize (
void * pUserData
)
{
return _msize_dbg(pUserData, _NORMAL_BLOCK);
}
/***
*size_t _msize_dbg() - calculate the size of specified block in the heap
*
*Purpose:
* Calculates the size of memory block (in the heap) pointed to by
* pUserData.
*
*Entry:
* void * pUserData - pointer to a (user portion) of memory block in the
* debug heap
* int nBlockUse - block type
*
* For any type of supported block.
*
*Return:
* size of the block
*
*******************************************************************************/
_CRTIMP size_t __cdecl _msize_dbg (
void * pUserData,
int nBlockUse
)
{
size_t nSize;
_CrtMemBlockHeader * pHead;
/* verify heap before getting size */
if (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)
_ASSERTE(_CrtCheckMemory());
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
/*
* 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));
/* CRT blocks can be treated as NORMAL blocks */
if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
nBlockUse = _CRT_BLOCK;
if (pHead->nBlockUse != _IGNORE_BLOCK)
_ASSERTE(pHead->nBlockUse == nBlockUse);
nSize = pHead->nDataSize;
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
return nSize;
}
/***
*long _CrtSetBreakAlloc() - set allocation on which to break
*
*Purpose:
* set allocation on which to break
*
*Entry:
* long lBreakAlloc
*
*Exit:
* return previous break number
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP long __cdecl _CrtSetBreakAlloc(
long lNewBreakAlloc
)
{
long lOldBreakAlloc = _crtBreakAlloc;
_crtBreakAlloc = lNewBreakAlloc;
return lOldBreakAlloc;
}
/***
*void _CrtSetDbgBlockType() - change memory block type
*
*Purpose:
* change memory block type
*
*Entry:
* void * pUserData - pointer to a (user portion) of memory block in the
* debug heap
* int nBlockUse - block type
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP void __cdecl _CrtSetDbgBlockType(
void * pUserData,
int nBlockUse
)
{
_CrtMemBlockHeader * pHead;
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
/* If from local heap, then change block type. */
if (_CrtIsValidHeapPointer(pUserData))
{
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
pHead->nBlockUse = nBlockUse;
}
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
return;
}
/*---------------------------------------------------------------------------
*
* Client-defined allocation hook
*
--------------------------------------------------------------------------*/
/***
*_CRT_ALLOC_HOOK _CrtSetAllocHook() - set client allocation hook
*
*Purpose:
* set client allocation hook
*
*Entry:
* _CRT_ALLOC_HOOK pfnNewHook - new allocation hook
*
*Exit:
* return previous hook
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP _CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook(
_CRT_ALLOC_HOOK pfnNewHook
)
{
_CRT_ALLOC_HOOK pfnOldHook = _pfnAllocHook;
_pfnAllocHook = pfnNewHook;
return pfnOldHook;
}
/*---------------------------------------------------------------------------
*
* Memory management
*
--------------------------------------------------------------------------*/
/***
*static int CheckBytes() - verify byte range set to proper value
*
*Purpose:
* verify byte range set to proper value
*
*Entry:
* unsigned char *pb - pointer to start of byte range
* unsigned char bCheck - value byte range should be set to
* size_t nSize - size of byte range to be checked
*
*Return:
* TRUE - if all bytes in range equal bcheck
* FALSE otherwise
*
*******************************************************************************/
static int __cdecl CheckBytes(
unsigned char * pb,
unsigned char bCheck,
size_t nSize
)
{
int bOkay = TRUE;
while (nSize--)
{
if (*pb++ != bCheck)
{
_RPT3(_CRT_WARN, "memory check error at 0x%08X = 0x%02X, should be 0x%02X.\n",
(BYTE *)(pb-1),*(pb-1), bCheck);
bOkay = FALSE;
}
}
return bOkay;
}
/***
*int _CrtCheckMemory() - check heap integrity
*
*Purpose:
* Confirm integrity of debug heap. Call _heapchk to validate underlying
* heap.
*
*Entry:
* void
*
*Return:
* TRUE - if debug and underlying heap appear valid
* FALSE otherwise
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtCheckMemory(
void
)
{
int allOkay;
int nHeapCheck;
_CrtMemBlockHeader * pHead;
if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
return TRUE; /* can't do any checking */
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
/* check underlying heap */
nHeapCheck = _heapchk();
if (nHeapCheck != _HEAPEMPTY && nHeapCheck != _HEAPOK)
{
switch (nHeapCheck)
{
case _HEAPBADBEGIN:
_RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADBEGIN.\n");
break;
case _HEAPBADNODE:
_RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADNODE.\n");
break;
case _HEAPEND:
_RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADEND.\n");
break;
case _HEAPBADPTR:
_RPT0(_CRT_WARN, "_heapchk fails with _HEAPBADPTR.\n");
break;
default:
_RPT0(_CRT_WARN, "_heapchk fails with unknown return value!\n");
break;
}
allOkay = FALSE;
}
else
{
allOkay = TRUE;
/* check all allocated blocks */
for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
{
int okay = TRUE; /* this block okay ? */
unsigned char * blockUse;
if (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))
blockUse = szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)];
else
blockUse = "DAMAGED";
/* check no-mans-land gaps */
if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
{
_RPT3(_CRT_WARN, "DAMAGE: before %hs block (#%d) at 0x%08X.\n",
blockUse, pHead->lRequest, (BYTE *) pbData(pHead));
okay = FALSE;
}
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill,
nNoMansLandSize))
{
_RPT3(_CRT_WARN, "DAMAGE: after %hs block (#%d) at 0x%08X.\n",
blockUse, pHead->lRequest, (BYTE *) pbData(pHead));
okay = FALSE;
}
/* free blocks should remain undisturbed */
if (pHead->nBlockUse == _FREE_BLOCK &&
!CheckBytes(pbData(pHead), _bDeadLandFill, pHead->nDataSize))
{
_RPT1(_CRT_WARN, "DAMAGE: on top of Free block at 0x%08X.\n",
(BYTE *) pbData(pHead));
okay = FALSE;
}
if (!okay)
{
/* report some more statistics about the broken object */
if (pHead->szFileName != NULL)
_RPT3(_CRT_WARN, "%hs allocated at file %hs(%d).\n",
blockUse, pHead->szFileName, pHead->nLine);
_RPT3(_CRT_WARN, "%hs located at 0x%08X is %u bytes long.\n",
blockUse, (BYTE *)pbData(pHead), pHead->nDataSize);
allOkay = FALSE;
}
}
}
#ifdef _MT
}
__finally {
_munlock( _HEAP_LOCK ); /* release other threads */
}
#endif /* _MT */
return allOkay;
}
/***
*int _CrtSetDbgFlag() - get/set the _crtDbgFlag
*
*Purpose:
* get or set the _crtDbgFlag
*
*Entry:
* int bNewBits - new Flag or _CRTDBG_REPORT_FLAG
*
*Return:
* previous flag state
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtSetDbgFlag(
int fNewBits
)
{
int fOldBits = _crtDbgFlag;
if (fNewBits != _CRTDBG_REPORT_FLAG)
_crtDbgFlag = fNewBits;
return fOldBits;
}
/***
*int _CrtDoForAllClientObjects() - call a client-supplied function for all
* client objects in the heap
*
*Purpose:
* call a client-supplied function for all client objects in the heap
*
*Entry:
* void (*pfn)(void *, void *) - pointer to client function to call
* void * pContext - pointer to user supplied context to pass to function
*
*Return:
* void
*
*******************************************************************************/
_CRTIMP void __cdecl _CrtDoForAllClientObjects(
void (*pfn)(void *, void *),
void * pContext
)
{
_CrtMemBlockHeader * pHead;
if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
return; /* sorry not enabled */
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
{
if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
(*pfn)((void *) pbData(pHead), pContext);
}
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
}
/***
*int _CrtIsValidPointer() - verify memory range is valid for reading/writing
*
*Purpose:
* verify memory range range is valid for reading/writing
*
*Entry:
* const void * pv - start of memory range to test
* unsigned int nBytes - size of memory range
* int bReadWrite - TRUE if read/write, FALSE if read-only
*
*Return:
* TRUE - if valid address
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -