mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 17:59:37 +00:00
1
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "pch_tier0.h"
|
||||
|
||||
#include "tier0/memblockhdr.h"
|
||||
|
||||
|
||||
#ifdef DBGFLAG_VALIDATE
|
||||
|
||||
// we use malloc & free internally in our validation code; turn off the deprecation #defines
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CValidator::CValidator( )
|
||||
{
|
||||
m_pValObjectFirst = NULL;
|
||||
m_pValObjectLast = NULL;
|
||||
m_pValObjectCur = NULL;
|
||||
m_cpvOwned = 0;
|
||||
m_bMemLeaks = false;
|
||||
|
||||
// Mark all memory blocks as unclaimed, prior to starting the validation process
|
||||
CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( ); // Head is just a placeholder
|
||||
while ( NULL != pMemBlockHdr )
|
||||
{
|
||||
pMemBlockHdr->SetBClaimed( false );
|
||||
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CValidator::~CValidator( )
|
||||
{
|
||||
CValObject *pValObject = m_pValObjectFirst;
|
||||
CValObject *pValObjectNext;
|
||||
while ( NULL != pValObject )
|
||||
{
|
||||
pValObjectNext = pValObject->PValObjectNext( );
|
||||
Destruct<CValObject> (pValObject);
|
||||
free( pValObject );
|
||||
pValObject = pValObjectNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Call this each time you start a new Validate() function. It creates
|
||||
// a new CValObject to track the caller.
|
||||
// Input: pchType - The caller's type (typically a class name)
|
||||
// pvObj - The caller (typically an object pointer)
|
||||
// pchName - The caller's individual name (typically a member var of another class)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::Push( tchar *pchType, void *pvObj, tchar *pchName )
|
||||
{
|
||||
// Create a new ValObject and add it to the linked list
|
||||
|
||||
CValObject *pValObjectNew = (CValObject *) malloc( sizeof (CValObject ) );
|
||||
Construct<CValObject> (pValObjectNew);
|
||||
pValObjectNew->Init( pchType, pvObj, pchName, m_pValObjectCur, m_pValObjectLast );
|
||||
m_pValObjectLast = pValObjectNew;
|
||||
if ( NULL == m_pValObjectFirst )
|
||||
m_pValObjectFirst = pValObjectNew;
|
||||
|
||||
// Make this the current object
|
||||
m_pValObjectCur = pValObjectNew;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Call this each time you end a Validate() function. It decrements
|
||||
// our current structure depth.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::Pop( )
|
||||
{
|
||||
Assert( NULL != m_pValObjectCur );
|
||||
m_pValObjectCur = m_pValObjectCur->PValObjectParent( );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Call this to register each memory block you own.
|
||||
// Input: pvMem - Memory block you own
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::ClaimMemory( void *pvMem )
|
||||
{
|
||||
if ( NULL == pvMem )
|
||||
return;
|
||||
|
||||
// Mark the block as owned
|
||||
CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFromPvUser( pvMem );
|
||||
pMemBlockHdr->CheckValid( );
|
||||
Assert( !pMemBlockHdr->BClaimed( ) );
|
||||
pMemBlockHdr->SetBClaimed( true );
|
||||
|
||||
// Let the current object know about it
|
||||
Assert( NULL != m_pValObjectCur );
|
||||
m_pValObjectCur->ClaimMemoryBlock( pvMem );
|
||||
|
||||
// Update our counter
|
||||
m_cpvOwned++;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: We're done enumerating our objects. Perform any final calculations.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::Finalize( void )
|
||||
{
|
||||
// Count our memory leaks
|
||||
CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
|
||||
m_cpubLeaked = 0;
|
||||
m_cubLeaked = 0;
|
||||
while ( NULL != pMemBlockHdr )
|
||||
{
|
||||
if ( !pMemBlockHdr->BClaimed( ) )
|
||||
{
|
||||
m_cpubLeaked++;
|
||||
m_cubLeaked += pMemBlockHdr->CubUser( );
|
||||
m_bMemLeaks = true;
|
||||
}
|
||||
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Render all reported objects to the console
|
||||
// Input: cubThreshold - Only render object whose children have at least
|
||||
// cubThreshold bytes allocated
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::RenderObjects( int cubThreshold )
|
||||
{
|
||||
// Walk our object list and render them all to the console
|
||||
CValObject *pValObject = m_pValObjectFirst;
|
||||
while ( NULL != pValObject )
|
||||
{
|
||||
if ( pValObject->CubMemTree( ) >= cubThreshold )
|
||||
{
|
||||
for ( int ich = 0; ich < pValObject->NLevel( ); ich++ )
|
||||
ConMsg( 2, _T(" ") );
|
||||
|
||||
ConMsg( 2, _T("%s at 0x%x--> %d blocks = %d bytes\n"),
|
||||
pValObject->PchType( ), pValObject->PvObj( ), pValObject->CpubMemTree( ),
|
||||
pValObject->CubMemTree( ) );
|
||||
}
|
||||
|
||||
pValObject = pValObject->PValObjectNext( );
|
||||
}
|
||||
|
||||
|
||||
// Dump a summary to the console
|
||||
ConMsg( 2, _T("Allocated:\t%d blocks\t%d bytes\n"), CpubAllocated( ), CubAllocated( ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Render any discovered memory leaks to the console
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::RenderLeaks( void )
|
||||
{
|
||||
if ( m_bMemLeaks )
|
||||
ConMsg( 1, _T("\n") );
|
||||
|
||||
// Render any leaked blocks to the console
|
||||
CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
|
||||
while ( NULL != pMemBlockHdr )
|
||||
{
|
||||
if ( !pMemBlockHdr->BClaimed( ) )
|
||||
{
|
||||
ConMsg( 1, _T("Leaked mem block: Addr = 0x%x\tSize = %d\n"),
|
||||
pMemBlockHdr->PvUser( ), pMemBlockHdr->CubUser( ) );
|
||||
ConMsg( 1, _T("\tAlloc = %s, line %d\n"),
|
||||
pMemBlockHdr->PchFile( ), pMemBlockHdr->NLine( ) );
|
||||
}
|
||||
|
||||
pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
|
||||
}
|
||||
|
||||
// Dump a summary to the console
|
||||
if ( 0 != m_cpubLeaked )
|
||||
ConMsg( 1, _T("!!!Leaked:\t%d blocks\t%d bytes\n"), m_cpubLeaked, m_cubLeaked );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find the validator object associated with the given real object.
|
||||
//-----------------------------------------------------------------------------
|
||||
CValObject *CValidator::FindObject( void * pvObj )
|
||||
{
|
||||
CValObject *pValObject = m_pValObjectFirst;
|
||||
CValObject *pValObjectNext;
|
||||
while ( NULL != pValObject )
|
||||
{
|
||||
pValObjectNext = pValObject->PValObjectNext( );
|
||||
if( pvObj == pValObject->PvObj() )
|
||||
return pValObject;
|
||||
|
||||
pValObject = pValObjectNext;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Diff one CValidator against another. Each Validator object is
|
||||
// tagged with whether it is new since the last snapshot or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CValidator::DiffAgainst( CValidator *pOtherValidator ) // Removes any entries from this validator that are also present in the other.
|
||||
{
|
||||
// Render any leaked blocks to the console
|
||||
CValObject *pValObject = m_pValObjectFirst;
|
||||
CValObject *pValObjectNext;
|
||||
while ( NULL != pValObject )
|
||||
{
|
||||
pValObjectNext = pValObject->PValObjectNext( );
|
||||
pValObject->SetBNewSinceSnapshot( pOtherValidator->FindObject( pValObject->PvObj() ) == NULL );
|
||||
|
||||
if( pValObject->BNewSinceSnapshot() && pValObject->CubMemTree( ) )
|
||||
{
|
||||
for ( int ich = 0; ich < pValObject->NLevel( ); ich++ )
|
||||
ConMsg( 2, _T(" ") );
|
||||
|
||||
ConMsg( 2, _T("%s at 0x%x--> %d blocks = %d bytes\n"),
|
||||
pValObject->PchType( ), pValObject->PvObj( ), pValObject->CpubMemTree( ),
|
||||
pValObject->CubMemTree( ) );
|
||||
}
|
||||
|
||||
pValObject = pValObjectNext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CValidator::Validate( CValidator &validator, tchar *pchName )
|
||||
{
|
||||
validator.Push( _T("CValidator"), this, pchName );
|
||||
|
||||
validator.ClaimMemory( this );
|
||||
|
||||
// Render any leaked blocks to the console
|
||||
CValObject *pValObject = m_pValObjectFirst;
|
||||
CValObject *pValObjectNext;
|
||||
while ( NULL != pValObject )
|
||||
{
|
||||
pValObjectNext = pValObject->PValObjectNext( );
|
||||
validator.ClaimMemory( pValObject );
|
||||
pValObject = pValObjectNext;
|
||||
}
|
||||
|
||||
validator.Pop();
|
||||
}
|
||||
|
||||
#endif // DBGFLAG_VALIDATE
|
||||
Reference in New Issue
Block a user