📄 dbgheap.c
字号:
* FALSE otherwise
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtIsValidPointer(
const void * pv,
unsigned int nBytes,
int bReadWrite
)
{
return (
pv != NULL
#ifdef _WIN32
&& !IsBadReadPtr(pv, nBytes) &&
(!bReadWrite || !IsBadWritePtr((LPVOID)pv, nBytes))
#endif /* _WIN32 */
);
}
/***
*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
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
#ifndef WINHEAP
int i;
void * base;
#endif /* WINHEAP */
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), TRUE))
return FALSE;
#ifdef WINHEAP
if ( __active_heap == __V6_HEAP )
{
PHEADER pHeader;
if (pHeader = __sbh_find_block(pHdr(pUserData)))
{
return __sbh_verify_block(pHeader, pHdr(pUserData));
}
else if ( (_osver & 0x8000) != 0 )
return TRUE;
else
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
else if ( __active_heap == __V5_HEAP )
{
__old_sbh_region_t * preg;
__old_sbh_page_t * ppage;
__old_page_map_t * pmap;
if ( (pmap = __old_sbh_find_block( pHdr(pUserData), &preg, &ppage )) !=
NULL )
{
if ( *pmap )
return TRUE;
else
return FALSE;
}
else if ( (_osver & 0x8000) != 0 )
return TRUE;
else
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
else // __active_heap == _SYSTEM_HEAP
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
#else /* WINHEAP */
/*
* Go through the heap regions and see if the pointer lies within one
* of the regions of the local heap.
*
* Pointers from non-local heaps cannot be handled. For example, a
* non-local pointer may come from a DLL that has the CRT linked-in.
*
*/
#ifdef _WIN32
for (i = 0; (base = _heap_regions[i]._regbase) != NULL &&
i < _HEAP_REGIONMAX; i++)
{
if (pUserData >= base && pUserData <
(void *)(((char *)base)+_heap_regions[i]._currsize))
return TRUE;
}
#else /* _WIN32 */
{
struct _heap_region_ *pHeapRegions
= (struct _heap_region_ *)(*hHeapRegions);
for (i = 0; (base = (pHeapRegions+i)->_regbase) != NULL &&
i < _HEAP_REGIONMAX; i++)
{
if (pUserData >= base && pUserData <
(void *)(((char *)base)+(pHeapRegions+i)->_currsize))
return TRUE;
}
}
#endif /* _WIN32 */
return FALSE;
#endif /* WINHEAP */
}
/***
*int _CrtIsMemoryBlock() - verify memory block is debug heap block
*
*Purpose:
* verify memory block is debug heap block
*
*Entry:
* const void * pUserData - start of memory block
* unsigned int nBytes - size of memory block
* long * plRequestNumber - if !NULL, set to request number
* char ** pszFileName - if !NULL, set to file name
* int * pnLine - if !NULL, set to line number
*
*Return:
* TRUE - if debug memory heap address
* FALSE otherwise
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtIsMemoryBlock(
const void * pUserData,
unsigned int nBytes,
long * plRequestNumber,
char ** pszFileName,
int * pnLine
)
{
_CrtMemBlockHeader * pHead;
int retval;
if (!_CrtIsValidHeapPointer(pUserData))
return FALSE;
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
pHead = pHdr(pUserData);
if (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) &&
_CrtIsValidPointer(pUserData, nBytes, TRUE) &&
pHead->nDataSize == nBytes &&
pHead->lRequest <= _lRequestCurr
)
{
if (plRequestNumber != NULL)
*plRequestNumber = pHead->lRequest;
if (pszFileName != NULL)
*pszFileName = pHead->szFileName;
if (pnLine != NULL)
*pnLine = pHead->nLine;
retval = TRUE;
}
else
retval = FALSE;
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
return retval;
}
/*---------------------------------------------------------------------------
*
* Memory state
*
--------------------------------------------------------------------------*/
/***
*_CRT_DUMP_CLIENT _CrtSetDumpClient() - set client dump routine
*
*Purpose:
* set client dump routine
*
*Entry:
* _CRT_DUMP_CLIENT pfnNewDumpClient - new dump routine
*
*Exit:
* return previous dump routine
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP _CRT_DUMP_CLIENT __cdecl _CrtSetDumpClient(
_CRT_DUMP_CLIENT pfnNewDump
)
{
_CRT_DUMP_CLIENT pfnOldDump = _pfnDumpClient;
_pfnDumpClient = pfnNewDump;
return pfnOldDump;
}
/***
*_CrtMemState * _CrtMemStateCheckpoint() - checkpoint current memory state
*
*Purpose:
* checkpoint current memory state
*
*Entry:
* _CrtMemState * state - state structure to fill in, will be
* allocated if NULL
*
*Return:
* current memory state
*
*******************************************************************************/
_CRTIMP void __cdecl _CrtMemCheckpoint(
_CrtMemState * state
)
{
int use;
_CrtMemBlockHeader * pHead;
if (state == NULL)
{
_RPT0(_CRT_WARN, "_CrtMemCheckPoint: NULL state pointer.\n");
return;
}
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
state->pBlockHeader = _pFirstBlock;
for (use = 0; use < _MAX_BLOCKS; use++)
state->lCounts[use] = state->lSizes[use] = 0;
for (pHead = _pFirstBlock; pHead != NULL; pHead = pHead->pBlockHeaderNext)
{
if (_BLOCK_TYPE(pHead->nBlockUse) >= 0 && _BLOCK_TYPE(pHead->nBlockUse) < _MAX_BLOCKS)
{
state->lCounts[_BLOCK_TYPE(pHead->nBlockUse)]++;
state->lSizes[_BLOCK_TYPE(pHead->nBlockUse)] += pHead->nDataSize;
}
else
{
_RPT1(_CRT_WARN, "Bad memory block found at 0x%08X.\n", (BYTE *)pHead);
}
}
state->lHighWaterCount = _lMaxAlloc;
state->lTotalCount = _lTotalAlloc;
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
}
/***
*int _CrtMemDifference() - compare two memory states
*
*Purpose:
* compare two memory states
*
*Entry:
* _CrtMemState * state - return memory state difference
* _CrtMemState * oldState - earlier memory state
* _CrtMemState * newState - later memory state
*
*Return:
* TRUE if difference
* FALSE otherwise
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtMemDifference(
_CrtMemState * state,
const _CrtMemState * oldState,
const _CrtMemState * newState
)
{
int use;
int bSignificantDifference = FALSE;
if (state == NULL || oldState == NULL || newState == NULL)
{
_RPT0(_CRT_WARN, "_CrtMemDifference: NULL state pointer.\n");
return bSignificantDifference;
}
for (use = 0; use < _MAX_BLOCKS; use++)
{
state->lSizes[use] = newState->lSizes[use] - oldState->lSizes[use];
state->lCounts[use] = newState->lCounts[use] - oldState->lCounts[use];
if ( (state->lSizes[use] != 0 || state->lCounts[use] != 0) &&
use != _FREE_BLOCK &&
(use != _CRT_BLOCK ||
(use == _CRT_BLOCK && (_crtDbgFlag & _CRTDBG_CHECK_CRT_DF)))
)
bSignificantDifference = TRUE;
}
state->lHighWaterCount = newState->lHighWaterCount - oldState->lHighWaterCount;
state->lTotalCount = newState->lTotalCount - oldState->lTotalCount;
state->pBlockHeader = NULL;
return bSignificantDifference;
}
#define MAXPRINT 16
static void __cdecl _printMemBlockData(
_CrtMemBlockHeader * pHead
)
{
int i;
unsigned char ch;
unsigned char printbuff[MAXPRINT+1];
unsigned char valbuff[MAXPRINT*3+1];
for (i = 0; i < min((int)pHead->nDataSize, MAXPRINT); i++)
{
ch = pbData(pHead)[i];
printbuff[i] = isprint(ch) ? ch : ' ';
sprintf(&valbuff[i*3], "%.2X ", ch);
}
printbuff[i] = '\0';
_RPT2(_CRT_WARN, " Data: <%s> %s\n", printbuff, valbuff);
}
/***
*void _CrtMemDumpAllObjectsSince() - dump all objects since memory state
*
*Purpose:
* dump all objects since memory state
*
*Entry:
* _CrtMemState * state - dump since this state
*
*Return:
* void
*
*******************************************************************************/
_CRTIMP void __cdecl _CrtMemDumpAllObjectsSince(
const _CrtMemState * state
)
{
_CrtMemBlockHeader * pHead;
_CrtMemBlockHeader * pStopBlock = NULL;
#ifdef _MT
_mlock(_HEAP_LOCK); /* block other threads */
__try {
#endif /* _MT */
_RPT0(_CRT_WARN, "Dumping objects ->\n");
if (state)
pStopBlock = state->pBlockHeader;
for (pHead = _pFirstBlock; pHead != NULL && pHead != pStopBlock;
pHead = pHead->pBlockHeaderNext)
{
if (_BLOCK_TYPE(pHead->nBlockUse) == _IGNORE_BLOCK ||
_BLOCK_TYPE(pHead->nBlockUse) == _FREE_BLOCK ||
(_BLOCK_TYPE(pHead->nBlockUse) == _CRT_BLOCK &&
!(_crtDbgFlag & _CRTDBG_CHECK_CRT_DF))
)
{
/* ignore it for dumping */
}
else {
if (pHead->szFileName != NULL)
{
if (!_CrtIsValidPointer(pHead->szFileName, 1, FALSE))
_RPT1(_CRT_WARN, "#File Error#(%d) : ", pHead->nLine);
else
_RPT2(_CRT_WARN, "%hs(%d) : ", pHead->szFileName, pHead->nLine);
}
_RPT1(_CRT_WARN, "{%ld} ", pHead->lRequest);
if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
{
_RPT3(_CRT_WARN, "client block at 0x%08X, subtype %x, %u bytes long.\n",
(BYTE *)pbData(pHead), _BLOCK_SUBTYPE(pHead->nBlockUse), pHead->nDataSize);
if (_pfnDumpClient)
(*_pfnDumpClient)( (void *) pbData(pHead), pHead->nDataSize);
else
_printMemBlockData(pHead);
}
else if (pHead->nBlockUse == _NORMAL_BLOCK)
{
_RPT2(_CRT_WARN, "normal block at 0x%08X, %u bytes long.\n",
(BYTE *)pbData(pHead), pHead->nDataSize);
_printMemBlockData(pHead);
}
else if (_BLOCK_TYPE(pHead->nBlockUse) == _CRT_BLOCK)
{
_RPT3(_CRT_WARN, "crt block at 0x%08X, subtype %x, %u bytes long.\n",
(BYTE *)pbData(pHead), _BLOCK_SUBTYPE(pHead->nBlockUse), pHead->nDataSize);
_printMemBlockData(pHead);
}
}
}
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK); /* release other threads */
}
#endif /* _MT */
_RPT0(_CRT_WARN, "Object dump complete.\n");
}
/***
*void _CrtMemDumpMemoryLeaks() - dump all objects still in heap
*
*Purpose:
* dump all objects still in heap. used to detect memory leaks over the
* life of a program
*
*Entry:
* void
*
*Return:
* TRUE if memory leaks
* FALSE otherwise
*
*******************************************************************************/
_CRTIMP int __cdecl _CrtDumpMemoryLeaks(
void
)
{
/* only dump leaks when there are in fact leaks */
_CrtMemState msNow;
_CrtMemCheckpoint(&msNow);
if (msNow.lCounts[_CLIENT_BLOCK] != 0 ||
msNow.lCounts[_NORMAL_BLOCK] != 0 ||
(_crtDbgFlag & _CRTDBG_CHECK_CRT_DF &&
msNow.lCounts[_CRT_BLOCK] != 0)
)
{
/* difference detected: dump objects since start. */
_RPT0(_CRT_WARN, "Detected memory leaks!\n");
_CrtMemDumpAllObjectsSince(NULL);
return TRUE;
}
return FALSE; /* no leaked objects */
}
/***
*_CrtMemState * _CrtMemDumpStatistics() - dump memory state
*
*Purpose:
* dump memory state
*
*Entry:
* _CrtMemState * state - dump this state
*
*Return:
* void
*
*******************************************************************************/
_CRTIMP void __cdecl _CrtMemDumpStatistics(
const _CrtMemState * state
)
{
int use;
if (state == NULL)
return;
for (use = 0; use < _MAX_BLOCKS; use++)
{
_RPT3(_CRT_WARN, "%ld bytes in %ld %hs Blocks.\n",
state->lSizes[use], state->lCounts[use], szBlockUseName[use]);
}
_RPT1(_CRT_WARN, "Largest number used: %ld bytes.\n", state->lHighWaterCount);
_RPT1(_CRT_WARN, "Total allocations: %ld bytes.\n", state->lTotalCount);
}
#endif /* _DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -