Memory.h

Go to the documentation of this file.
00001 
00002 
00014 
00015 //Luke Lenhart, 2001-2008
00016 //See /docs/License.txt for details on how this code may be used.
00017 
00018 #pragma once
00019 
00020 #include "Setup.h"
00021 
00022 // --
00023 
00024 #if defined(_DEBUG) || defined(ENABLE_MEMMAN_TRACE_IN_RELEASE)
00025     #define MEMMAN_TRACING
00026 #endif
00027 
00028 #include <list>
00029 #include <string>
00030 #include <string.h> //for memset
00031 #include "Types.h"
00032 #include "Locks.h"
00033 
00034 //internal use
00035 enum EMemAllocType
00036 {
00037     EMAT_None,
00038     EMAT_One,
00039     EMAT_Array
00040 };
00041 
00043 class MPMAMemoryManager
00044 {
00045 public:
00046     MPMAMemoryManager();
00047     ~MPMAMemoryManager();
00048 
00050     void AddLeakReportCallback(void (*leakCallback)(const std::string &leakMessage));
00051 
00052     //returns whether the memory manager is ready to handle requests
00053     inline bool IsReady() const
00054         { return m_ready; }
00055 
00056     //used by the allocation scheme, do not call directly - traces an alloc or free
00057     void TraceAlloc(EMemAllocType type, void *memory, void *object, uint objectSize, int count, const char *file, int line);
00058     EMemAllocType TraceFree(EMemAllocType type, volatile void *object, char *&outAllocMem, int *outObjectSize, int *outCount, const char *file, int line);
00059 
00060     //used by the allocation scheme, do not call directly
00061     void InternalInitialize();
00062     void InternalShutdown();
00063 
00064 #ifndef MEMMAN_TRACING // -- if NOT using management --
00065     //Returns if a specific pointer is an allocated object (always returns true if management is disabled)
00066     inline bool IsPointerAnObject(void *p)
00067         { return true; }
00068 
00069     //checks for memory corruption around all allocated memory
00070     inline void CheckForPaddingCorruption() {}
00071 #endif
00072 
00073 #ifdef MEMMAN_TRACING // -- if using management --
00074 
00075     //Returns if a specific pointer is an allocated object (always returns true if management is disabled)
00076     bool IsPointerAnObject(void *p);
00077 
00078     //checks for memory corruption around all allocated memory
00079     void CheckForPaddingCorruption();
00080 
00081     struct SAlloc
00082     {
00083         EMemAllocType type;
00084         void *objAddr; //object address
00085         void *allocMem; //container memory
00086         uint size;
00087         std::string srcFile;
00088         int srcLine;
00089         int count; //number in array
00090         std::string allocStack;
00091         std::string deleteStack;
00092 
00093         SAlloc *next;
00094 
00095         std::string Describe();
00096     };
00097 
00098 private:
00099     bool m_critErrors; //did any critical memory errors occur?
00100 
00101     SAlloc *m_head; //first item in linked list of allocations
00102 
00103     //used internally
00104     bool VerifyAllocPadding(uint8 *mem, uint objSize);
00105 
00106     //used as part of mapping the difference between the memory we provide for an object and the memory new return to the caller
00107     struct SMapAllocDifference
00108     {
00109         void *actual;
00110         void *returned;
00111     };
00112     std::list<SMapAllocDifference> allocDifferences;
00113     MPMA::MutexLock *allocDiffLock;
00114 
00115 #endif // -- end if using management --
00116 
00117     //calls back to the leak report callbacks
00118     void ReportLeak(const std::string &leak);
00119     std::list<void (*)(const std::string &)> leakCallbacks;
00120 
00121     bool m_ready; //class ready to handle requests
00122     MPMA::MutexLock *syncLock;
00123 
00124 public: //internal use, do not call directly
00125 #ifdef MEMMAN_TRACING // -- if using management --
00126     //calls an objects destructor
00127     template <typename T> static void dbgN2_Destruct(T *obj)
00128     {
00129         obj->~T();
00130     }
00131     template <typename T> static void dbgN2_Destruct_array(T *obj, int count)
00132     {
00133         for (int i=0; i<count; ++i)
00134         {
00135             obj->~T();
00136             ++obj;
00137         }
00138     }
00139 
00140     //used as part of tracking a allocation differences
00141     template <typename T> static T dbgN3_ReturnNew(T obj)
00142     {
00143         AllocDifferenceMapEnd(obj);
00144         return obj;
00145     }
00146 
00147     static void AllocDifferenceMapStart(void *mem);
00148     static void AllocDifferenceMapEnd(void *mem);
00149 
00150     static void* DeallocDifferenceMap(void *mem, bool pop);
00151 #endif // -- end if using management --
00152 };
00153 
00154 extern MPMAMemoryManager mpmaMemoryManager;
00155 
00156 #ifdef MEMMAN_TRACING // -- if using management --
00157 
00158 //bytes on each side of an allocation that are used to check for damage
00159 #define dbgN2_padding 8
00160 
00161 //allocators that store tracing information
00162 void* operator new(size_t objLen, MPMAMemoryManager *theMan, const char *file, int line);
00163 
00164 #define new3(obj)       MPMAMemoryManager::dbgN3_ReturnNew(new (&mpmaMemoryManager, __FILE__, __LINE__) obj)
00165 #define new2(obj, junk) new3(obj)
00166 
00167 void* operator new[](size_t objLen, MPMAMemoryManager *theMan, size_t count, const char *file, int line);
00168 
00169 #define new3_array(obj, count)       MPMAMemoryManager::dbgN3_ReturnNew(new (&mpmaMemoryManager, count, __FILE__, __LINE__) obj[count])
00170 #define new2_array(obj, count, junk) new3_array(obj, count)
00171 
00172 //freers that match the above allocators
00173 
00174 void operator delete(void *obj, MPMAMemoryManager *theMan, const char *file, int line);
00175 
00176 void operator delete[](void *obj, MPMAMemoryManager *theMan, size_t count, const char *file, int line);
00177 
00178 #define delete3(obj) \
00179 do { \
00180     void *pObj=(void*)(obj); \
00181     int count=0; \
00182     int objSize=0; \
00183     char *realMem=0; \
00184     EMemAllocType type=mpmaMemoryManager.TraceFree(EMAT_One, pObj, realMem, &objSize, &count, __FILE__, __LINE__); \
00185     if (type==EMAT_One) MPMAMemoryManager::dbgN2_Destruct(obj); \
00186     else if (type==EMAT_Array) MPMAMemoryManager::dbgN2_Destruct_array(obj, count); \
00187     memset(pObj, 0x7e, objSize); \
00188     delete[] realMem; \
00189     *((uint**)&obj)=(uint*)-1; \
00190 } while(false)
00191 
00192 #define delete2(obj) delete3(obj) 
00193 
00194 #define delete3_array(obj) \
00195 do { \
00196     void *pObj=(void*)(obj); \
00197     int count=0; \
00198     int objSize=0; \
00199     char *realMem=0; \
00200     EMemAllocType type=mpmaMemoryManager.TraceFree(EMAT_Array, pObj, realMem, &objSize, &count, __FILE__, __LINE__); \
00201     if (type==EMAT_One) MPMAMemoryManager::dbgN2_Destruct(obj); \
00202     else if (type==EMAT_Array) MPMAMemoryManager::dbgN2_Destruct_array(obj, count); \
00203     memset(pObj, 0x7e, objSize); \
00204     delete[] realMem; \
00205     *((uint**)&obj)=(uint*)-1; \
00206 } while(false)
00207 
00208 #define delete2_array(obj) delete3_array(obj)
00209 
00210 #else // -- if NOT using management --
00211 
00212     #define new3(obj) new obj
00213     #define new2(obj,junk) new obj
00214     #define new3_array(obj,count) new obj[count]
00215     #define new2_array(obj,count,junk) new obj[count]
00216 
00217     #define delete3(obj) delete obj
00218     #define delete2(obj) delete obj
00219     #define delete3_array(obj) delete[] obj
00220     #define delete2_array(obj) delete[] obj
00221 
00222 #endif // -- end if using management --
00223 
00224 
00225 // -- auto scope pointer freer --
00226 //will free a pointer when this goes out of scope (and it's not a null pointer)
00227 //pass in the ADDRESS of your pointer
00228 
00230 template <typename T>
00231 class AutoDelete
00232 {
00233 public:
00234     inline AutoDelete(T *inPtr): ptr(inPtr) {}
00235     inline ~AutoDelete() {if (ptr) delete2(ptr);}
00236 private:
00237     T *ptr;
00238 };
00239 
00241 template <typename T>
00242 class AutoDeleteArray
00243 {
00244 public:
00245     inline AutoDeleteArray(T *inPtr): ptr(inPtr) {}
00246     inline ~AutoDeleteArray() {if (ptr) delete2_array(ptr);}
00247 private:
00248     T *ptr;
00249 };

Generated on Sat Aug 9 15:05:05 2008 for MPMA Framework by  doxygen 1.5.6