summaryrefslogtreecommitdiff
path: root/tier0/validator.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier0/validator.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'tier0/validator.cpp')
-rw-r--r--tier0/validator.cpp268
1 files changed, 268 insertions, 0 deletions
diff --git a/tier0/validator.cpp b/tier0/validator.cpp
new file mode 100644
index 0000000..3f08fe0
--- /dev/null
+++ b/tier0/validator.cpp
@@ -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 \ No newline at end of file