Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
8.4 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "pch_tier0.h"
  8. #include "tier0/memblockhdr.h"
  9. // NOTE: This has to be the last file included!
  10. #include "tier0/memdbgon.h"
  11. #ifdef DBGFLAG_VALIDATE
  12. // we use malloc & free internally in our validation code; turn off the deprecation #defines
  13. #undef malloc
  14. #undef free
  15. //-----------------------------------------------------------------------------
  16. // Purpose: Constructor
  17. //-----------------------------------------------------------------------------
  18. CValidator::CValidator( )
  19. {
  20. m_pValObjectFirst = NULL;
  21. m_pValObjectLast = NULL;
  22. m_pValObjectCur = NULL;
  23. m_cpvOwned = 0;
  24. m_bMemLeaks = false;
  25. // Mark all memory blocks as unclaimed, prior to starting the validation process
  26. CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
  27. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( ); // Head is just a placeholder
  28. while ( NULL != pMemBlockHdr )
  29. {
  30. pMemBlockHdr->SetBClaimed( false );
  31. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
  32. }
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Purpose: Destructor
  36. //-----------------------------------------------------------------------------
  37. CValidator::~CValidator( )
  38. {
  39. CValObject *pValObject = m_pValObjectFirst;
  40. CValObject *pValObjectNext;
  41. while ( NULL != pValObject )
  42. {
  43. pValObjectNext = pValObject->PValObjectNext( );
  44. Destruct<CValObject> (pValObject);
  45. free( pValObject );
  46. pValObject = pValObjectNext;
  47. }
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Call this each time you start a new Validate() function. It creates
  51. // a new CValObject to track the caller.
  52. // Input: pchType - The caller's type (typically a class name)
  53. // pvObj - The caller (typically an object pointer)
  54. // pchName - The caller's individual name (typically a member var of another class)
  55. //-----------------------------------------------------------------------------
  56. void CValidator::Push( tchar *pchType, void *pvObj, tchar *pchName )
  57. {
  58. // Create a new ValObject and add it to the linked list
  59. CValObject *pValObjectNew = (CValObject *) malloc( sizeof (CValObject ) );
  60. Construct<CValObject> (pValObjectNew);
  61. pValObjectNew->Init( pchType, pvObj, pchName, m_pValObjectCur, m_pValObjectLast );
  62. m_pValObjectLast = pValObjectNew;
  63. if ( NULL == m_pValObjectFirst )
  64. m_pValObjectFirst = pValObjectNew;
  65. // Make this the current object
  66. m_pValObjectCur = pValObjectNew;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: Call this each time you end a Validate() function. It decrements
  70. // our current structure depth.
  71. //-----------------------------------------------------------------------------
  72. void CValidator::Pop( )
  73. {
  74. Assert( NULL != m_pValObjectCur );
  75. m_pValObjectCur = m_pValObjectCur->PValObjectParent( );
  76. }
  77. //-----------------------------------------------------------------------------
  78. // Purpose: Call this to register each memory block you own.
  79. // Input: pvMem - Memory block you own
  80. //-----------------------------------------------------------------------------
  81. void CValidator::ClaimMemory( void *pvMem )
  82. {
  83. if ( NULL == pvMem )
  84. return;
  85. // Mark the block as owned
  86. CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFromPvUser( pvMem );
  87. pMemBlockHdr->CheckValid( );
  88. Assert( !pMemBlockHdr->BClaimed( ) );
  89. pMemBlockHdr->SetBClaimed( true );
  90. // Let the current object know about it
  91. Assert( NULL != m_pValObjectCur );
  92. m_pValObjectCur->ClaimMemoryBlock( pvMem );
  93. // Update our counter
  94. m_cpvOwned++;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: We're done enumerating our objects. Perform any final calculations.
  98. //-----------------------------------------------------------------------------
  99. void CValidator::Finalize( void )
  100. {
  101. // Count our memory leaks
  102. CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
  103. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
  104. m_cpubLeaked = 0;
  105. m_cubLeaked = 0;
  106. while ( NULL != pMemBlockHdr )
  107. {
  108. if ( !pMemBlockHdr->BClaimed( ) )
  109. {
  110. m_cpubLeaked++;
  111. m_cubLeaked += pMemBlockHdr->CubUser( );
  112. m_bMemLeaks = true;
  113. }
  114. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
  115. }
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose: Render all reported objects to the console
  119. // Input: cubThreshold - Only render object whose children have at least
  120. // cubThreshold bytes allocated
  121. //-----------------------------------------------------------------------------
  122. void CValidator::RenderObjects( int cubThreshold )
  123. {
  124. // Walk our object list and render them all to the console
  125. CValObject *pValObject = m_pValObjectFirst;
  126. while ( NULL != pValObject )
  127. {
  128. if ( pValObject->CubMemTree( ) >= cubThreshold )
  129. {
  130. for ( int ich = 0; ich < pValObject->NLevel( ); ich++ )
  131. ConMsg( 2, _T(" ") );
  132. ConMsg( 2, _T("%s at 0x%x--> %d blocks = %d bytes\n"),
  133. pValObject->PchType( ), pValObject->PvObj( ), pValObject->CpubMemTree( ),
  134. pValObject->CubMemTree( ) );
  135. }
  136. pValObject = pValObject->PValObjectNext( );
  137. }
  138. // Dump a summary to the console
  139. ConMsg( 2, _T("Allocated:\t%d blocks\t%d bytes\n"), CpubAllocated( ), CubAllocated( ) );
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Purpose: Render any discovered memory leaks to the console
  143. //-----------------------------------------------------------------------------
  144. void CValidator::RenderLeaks( void )
  145. {
  146. if ( m_bMemLeaks )
  147. ConMsg( 1, _T("\n") );
  148. // Render any leaked blocks to the console
  149. CMemBlockHdr *pMemBlockHdr = CMemBlockHdr::PMemBlockHdrFirst( );
  150. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
  151. while ( NULL != pMemBlockHdr )
  152. {
  153. if ( !pMemBlockHdr->BClaimed( ) )
  154. {
  155. ConMsg( 1, _T("Leaked mem block: Addr = 0x%x\tSize = %d\n"),
  156. pMemBlockHdr->PvUser( ), pMemBlockHdr->CubUser( ) );
  157. ConMsg( 1, _T("\tAlloc = %s, line %d\n"),
  158. pMemBlockHdr->PchFile( ), pMemBlockHdr->NLine( ) );
  159. }
  160. pMemBlockHdr = pMemBlockHdr->PMemBlockHdrNext( );
  161. }
  162. // Dump a summary to the console
  163. if ( 0 != m_cpubLeaked )
  164. ConMsg( 1, _T("!!!Leaked:\t%d blocks\t%d bytes\n"), m_cpubLeaked, m_cubLeaked );
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose: Find the validator object associated with the given real object.
  168. //-----------------------------------------------------------------------------
  169. CValObject *CValidator::FindObject( void * pvObj )
  170. {
  171. CValObject *pValObject = m_pValObjectFirst;
  172. CValObject *pValObjectNext;
  173. while ( NULL != pValObject )
  174. {
  175. pValObjectNext = pValObject->PValObjectNext( );
  176. if( pvObj == pValObject->PvObj() )
  177. return pValObject;
  178. pValObject = pValObjectNext;
  179. }
  180. return NULL;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose: Diff one CValidator against another. Each Validator object is
  184. // tagged with whether it is new since the last snapshot or not.
  185. //-----------------------------------------------------------------------------
  186. void CValidator::DiffAgainst( CValidator *pOtherValidator ) // Removes any entries from this validator that are also present in the other.
  187. {
  188. // Render any leaked blocks to the console
  189. CValObject *pValObject = m_pValObjectFirst;
  190. CValObject *pValObjectNext;
  191. while ( NULL != pValObject )
  192. {
  193. pValObjectNext = pValObject->PValObjectNext( );
  194. pValObject->SetBNewSinceSnapshot( pOtherValidator->FindObject( pValObject->PvObj() ) == NULL );
  195. if( pValObject->BNewSinceSnapshot() && pValObject->CubMemTree( ) )
  196. {
  197. for ( int ich = 0; ich < pValObject->NLevel( ); ich++ )
  198. ConMsg( 2, _T(" ") );
  199. ConMsg( 2, _T("%s at 0x%x--> %d blocks = %d bytes\n"),
  200. pValObject->PchType( ), pValObject->PvObj( ), pValObject->CpubMemTree( ),
  201. pValObject->CubMemTree( ) );
  202. }
  203. pValObject = pValObjectNext;
  204. }
  205. }
  206. void CValidator::Validate( CValidator &validator, tchar *pchName )
  207. {
  208. validator.Push( _T("CValidator"), this, pchName );
  209. validator.ClaimMemory( this );
  210. // Render any leaked blocks to the console
  211. CValObject *pValObject = m_pValObjectFirst;
  212. CValObject *pValObjectNext;
  213. while ( NULL != pValObject )
  214. {
  215. pValObjectNext = pValObject->PValObjectNext( );
  216. validator.ClaimMemory( pValObject );
  217. pValObject = pValObjectNext;
  218. }
  219. validator.Pop();
  220. }
  221. #endif // DBGFLAG_VALIDATE