1 /* 2 * Modification History 3 * 4 * 2002-October-17 Jason Rohrer 5 * Created. 6 * 7 * 2002-October-18 Jason Rohrer 8 * Changed to use custom list instead of SimpleVector because SimpleVector 9 * uses debugMemory. 10 * Added static initialization counting class. 11 * Changed to use struct and malloc for AllocationList to avoid 12 * circular new and delete calls. 13 * 14 * 2002-October-19 Jason Rohrer 15 * Changed to print leak list upon final destruction. 16 * Improved printing behavior. 17 * Added support for clearing memory on allocation and deallocation. 18 * 19 * 2002-October-20 Jason Rohrer 20 * Removed file and line arguments from deallocation calls. 21 */ 22 23 24 25 #ifndef MEMORY_TRACK_INCLUDED 26 #define MEMORY_TRACK_INCLUDED 27 28 29 30 #include "minorGems/system/MutexLock.h" 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 35 #define SINGLE_ALLOCATION 0 36 #define ARRAY_ALLOCATION 1 37 38 39 40 /** 41 * Linked list of memory allocations. 42 * 43 * @author Jason Rohrer 44 */ 45 typedef struct { 46 47 void *mPrevious; 48 void *mNext; 49 50 void *mPointer; 51 unsigned int mAllocationSize; 52 int mAllocationType; 53 const char *mFileName; 54 int mLineNumber; 55 56 } AllocationList; 57 58 59 60 /** 61 * Class that tracks memory allocations and deallocations. 62 * 63 * @author Jason Rohrer 64 */ 65 class MemoryTrack { 66 67 68 69 public: 70 71 72 73 /** 74 * Adds an allocation to this tracker and clears the allocated 75 * memory block. 76 * 77 * @param inPointer a pointer to the allocated memory. 78 * @param inAllocationType the type of allocation, 79 * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. 80 * @param inAllocationSize the size of the allocation in bytes. 81 * @param inFileName the name of the source file in which the 82 * allocation took place. 83 * @param inLineNumber the line number in the source file 84 * on which the allocation took place. 85 */ 86 static void addAllocation( void *inPointer, 87 unsigned int inAllocationSize, 88 int inAllocationType, 89 const char *inFileName, 90 int inLineNumber ); 91 92 93 94 /** 95 * Adds a deallocation to this tracker and clears the block 96 * to be deallocated. 97 * Must be called *before* the memory is deallocated 98 * 99 * @param inPointer a pointer to the memory being deallocated. 100 * @param inDeallocationType the type of deallocation, 101 * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. 102 * @return 0 if the deallocation deallocates 103 * an allocated block of memory, or 1 if it 104 * deallocates a block of memory that is not currently allocated, 105 * and 2 if it is the wrong deallocation type for the specified 106 * block. 107 */ 108 static int addDeallocation( void *inPointer, int inDeallocationType ); 109 110 111 112 113 /** 114 * Prints a list of all memory leaks (allocations that have never 115 * been deallocated). 116 */ 117 static void printLeaks(); 118 119 120 121 // these are public so initializer can get to them 122 123 static MutexLock *mLock; 124 125 // dummy place holder for list head 126 static AllocationList *mListHead; 127 128 // true if we're tracking 129 static char mTracking; 130 131 static int mTotalAllocationSize; 132 133 static int mTotalDeallocationSize; 134 135 static int mNumberOfAllocations; 136 137 protected: 138 139 140 141 /** 142 * Clears memory so that reading from it will not produce 143 * anything useful. Good for checking for reads to memory that 144 * has been deallocated. 145 * 146 * @param inPointer pointer to the memory to clear. 147 * @Param inSize the number of bytes to clear starting at inPointer. 148 */ 149 static void clearMemory( void *inPointer, unsigned int inSize ); 150 151 152 153 }; 154 155 156 157 /** 158 * Class that initializes MemoryTrack's static members. 159 * 160 * *All* files that use MemoryTrack will instantiate a static 161 * instance of this class (see static instance below). 162 * 163 * This class counts how many static instantiations have happened so 164 * far, making sure to init/destroy MemoryTrack's static members only once. 165 * 166 * Adapted from: 167 * http://www.hlrs.de/organization/par/services/tools/docu/kcc/ 168 * tutorials/static_initialization.html 169 */ 170 class MemoryTrackStaticInitCounter { 171 172 173 public: 174 175 176 MemoryTrackStaticInitCounter()177 MemoryTrackStaticInitCounter() { 178 if( mCount == 0 ) { 179 // allocate static members 180 MemoryTrack::mLock = new MutexLock(); 181 182 MemoryTrack::mListHead = 183 (AllocationList *) 184 malloc( sizeof( AllocationList ) ); 185 MemoryTrack::mListHead->mPrevious = NULL; 186 MemoryTrack::mListHead->mNext = NULL; 187 188 MemoryTrack::mTotalAllocationSize = 0; 189 MemoryTrack::mTotalDeallocationSize = 0; 190 MemoryTrack::mNumberOfAllocations = 0; 191 192 MemoryTrack::mTracking = true; 193 } 194 mCount++; 195 } 196 197 198 ~MemoryTrackStaticInitCounter()199 ~MemoryTrackStaticInitCounter() { 200 mCount--; 201 if( mCount == 0 ) { 202 // print leaks... we should only get here after 203 // all static members of classes that use MemoryTrack 204 // have been destroyed. 205 MemoryTrack::printLeaks(); 206 207 MemoryTrack::mTracking = false; 208 // deallocate static members 209 free( MemoryTrack::mListHead ); 210 delete MemoryTrack::mLock; 211 } 212 } 213 214 215 private: 216 // only allocate/deallocate when mCount == 0 217 static int mCount; 218 219 }; 220 221 222 223 // This will be included in *every* file that includes MemoryTrack.h 224 static MemoryTrackStaticInitCounter memoryTrackInitializer; 225 226 227 228 #endif 229 230 231