📄 dbgheap.c
字号:
return pfnOldHook;
}
/***
*_CRT_ALLOC_HOOK _CrtGetAllocHook() - get client allocation hook
*
*Purpose:
* get client allocation hook
*
*Entry:
*
*Exit:
* return current hook
*
*Exceptions:
*
*******************************************************************************/
extern "C" _CRTIMP _CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook
(
void
)
{
return _pfnAllocHook;
}
/*---------------------------------------------------------------------------
*
* 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
*
*******************************************************************************/
extern "C" static int __cdecl CheckBytes(
unsigned char * pb,
unsigned char bCheck,
size_t nSize
)
{
while (nSize--)
{
if (*pb++ != bCheck)
{
return FALSE;
}
}
return TRUE;
}
/***
*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
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtCheckMemory(
void
)
{
int allOkay;
int nHeapCheck;
_CrtMemBlockHeader * pHead;
if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
return TRUE; /* can't do any checking */
_mlock(_HEAP_LOCK); /* block other threads */
__try {
/* 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 = (unsigned char *)szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)];
else
blockUse = (unsigned char *)"DAMAGED";
/* check no-mans-land gaps */
if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
{
if (pHead->szFileName)
{
_RPT5(_CRT_WARN, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
"CRT detected that the application wrote to memory before start of heap buffer.\n"
_ALLOCATION_FILE_LINENUM,
blockUse,
pHead->lRequest,
(BYTE *) pbData(pHead),
pHead->szFileName,
pHead->nLine);
}
else
{
_RPT3(_CRT_WARN, "HEAP CORRUPTION DETECTED: before %hs block (#%d) at 0x%p.\n"
"CRT detected that the application wrote to memory before start of heap buffer.\n",
blockUse, pHead->lRequest, (BYTE *) pbData(pHead));
}
okay = FALSE;
}
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill,
nNoMansLandSize))
{
if (pHead->szFileName)
{
_RPT5(_CRT_WARN, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
"CRT detected that the application wrote to memory after end of heap buffer.\n"
_ALLOCATION_FILE_LINENUM,
blockUse,
pHead->lRequest,
(BYTE *) pbData(pHead),
pHead->szFileName,
pHead->nLine);
}
else
{
_RPT3(_CRT_WARN, "HEAP CORRUPTION DETECTED: after %hs block (#%d) at 0x%p.\n"
"CRT detected that the application wrote to memory after end of heap buffer.\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))
{
if (pHead->szFileName)
{
_RPT3(_CRT_WARN, "HEAP CORRUPTION DETECTED: on top of Free block at 0x%p.\n"
"CRT detected that the application wrote to a heap buffer that was freed.\n"
_ALLOCATION_FILE_LINENUM,
(BYTE *) pbData(pHead),
pHead->szFileName,
pHead->nLine);
}
else
{
_RPT1(_CRT_WARN, "HEAP CORRUPTION DETECTED: on top of Free block at 0x%p.\n"
"CRT detected that the application wrote to a heap buffer that was freed.\n",
(BYTE *) pbData(pHead));
}
okay = FALSE;
}
if (!okay)
{
/* report some more statistics about the broken object */
if (pHead->szFileName)
{
_RPT5(_CRT_WARN,
"%hs located at 0x%p is %Iu bytes long.\n"
_ALLOCATION_FILE_LINENUM,
blockUse,
(BYTE *)pbData(pHead),
pHead->nDataSize,
pHead->szFileName,
pHead->nLine);
}
else
{
_RPT3(_CRT_WARN, "%hs located at 0x%p is %Iu bytes long.\n",
blockUse, (BYTE *)pbData(pHead), pHead->nDataSize);
}
allOkay = FALSE;
}
}
}
}
__finally {
_munlock( _HEAP_LOCK ); /* release other threads */
}
return allOkay;
}
/***
*int _CrtSetDbgFlag() - get/set the _crtDbgFlag
*
*Purpose:
* get or set the _crtDbgFlag
*
*Entry:
* int fNewBits - new Flag or _CRTDBG_REPORT_FLAG
*
*Return:
* previous flag state
*
*Exceptions:
* The new flag need to use only _CRTDBG_ALLOC_MEM_DF, _CRTDBG_DELAY_FREE_MEM_DF,
* _CRTDBG_CHECK_ALWAYS_DF, _CRTDBG_CHECK_CRT_DF and _CRTDBG_LEAK_CHECK_DF. Otherwise
* errno is set to EINVAL and the flag is not changed.
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtSetDbgFlag(
int fNewBits
)
{
int fOldBits= _crtDbgFlag;
/* Make sure the flag uses only _CRTDBG_ALLOC_MEM_DF, _CRTDBG_DELAY_FREE_MEM_DF,
* _CRTDBG_CHECK_ALWAYS_DF, _CRTDBG_CHECK_CRT_DF and _CRTDBG_LEAK_CHECK_DF
*/
_VALIDATE_RETURN( (fNewBits==_CRTDBG_REPORT_FLAG) ||
((fNewBits & 0x0ffff &
~(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF |
_CRTDBG_LEAK_CHECK_DF)
) == 0),
EINVAL,
_crtDbgFlag);
_mlock(_HEAP_LOCK); /* block other threads */
__try {
// deliberate reinit here now we own the lock to ensure we pick up the most recent values
fOldBits = _crtDbgFlag;
if ( fNewBits != _CRTDBG_REPORT_FLAG )
{
if ( fNewBits & _CRTDBG_CHECK_ALWAYS_DF )
check_frequency = 1;
else
check_frequency = (fNewBits >> 16) & 0x0ffff;
check_counter = 0;
_crtDbgFlag = fNewBits;
}
}
__finally {
_munlock( _HEAP_LOCK );
}
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
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
extern "C" _CRTIMP void __cdecl _CrtDoForAllClientObjects(
void (*pfn)(void *, void *),
void * pContext
)
{
_CrtMemBlockHeader * pHead;
/* validation section */
_VALIDATE_RETURN_VOID(pfn != NULL, EINVAL);
if (!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
return; /* sorry not enabled */
_mlock(_HEAP_LOCK); /* block other threads */
__try {
for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
{
if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
(*pfn)((void *) pbData(pHead), pContext);
}
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
}
/***
*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
* FALSE otherwise
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtIsValidPointer(
const void * pv,
unsigned int nBytes,
int bReadWrite
)
{
return (pv != NULL);
}
/***
*int _CrtIsValidHeapPointer() - verify pointer is from 'local' heap
*
*Purpose:
* Verify pointer is not only a valid pointer but also that it is from
* the 'local' heap. Pointers from another copy of the C runtime (even in the
* same process) will be caught.
*
*Entry:
* const void * pUserData - pointer of interest
*
*Return:
* TRUE - if valid and from local heap
* FALSE otherwise
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
/***
*int _CrtIsMemoryBlock() - verify memory block is debug heap block
*
*Purpose:
* verify memory block is debug heap block
*
*Entry:
* con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -