/*****************************************************************************
*dbgheap.c - Debug CRT Heap Functions
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Defines debug versions of heap functions.
*
*******************************************************************************/
/*---------------------------------------------------------------------------
*
* 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
)
{
int bOkay = TRUE;
while (nSize--)
{
if (*pb++ != bCheck)
{
/* Internal error report is just noise; calling functions all report results - JWM */
/* _RPT3(_CRT_WARN, "memory check error at 0x%p = 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
*
*******************************************************************************/
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))
{
_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))
{
_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))
{
_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 != NULL)
_RPT3(_CRT_WARN, "%hs allocated at file %hs(%d)./n",
blockUse, pHead->szFileName, pHead->nLine);
_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;
}