00001 
00002 
00015 
00016 
00017 
00018 
00019 #pragma once
00020 
00021 #include "Setup.h"
00022 
00023 
00024 #if defined(_WIN32) || defined(_WIN64)
00025 #pragma warning(disable:4127) //conditional expression is constant.  example: do { ...etc... } while (false)
00026 #pragma warning(disable:4100) //unreferenced format parameter.  This seems to be a compiler bug... calling a destructor doesn't count as a "reference to" apparently.
00027 #endif
00028 
00029 
00030 
00031 
00032 #include <list>
00033 #include <string>
00034 #include <string.h> 
00035 #include "Types.h"
00036 
00037 
00038 enum EMemAllocType
00039 {
00040     EMAT_None,
00041     EMAT_One,
00042     EMAT_Array
00043 };
00044 
00046 class MPMAMemoryManager
00047 {
00048 public:
00049     
00050     inline bool IsReady() const
00051         { return m_ready; }
00052 
00053     
00054     void MarkAsIntentionallyLeaked(void *mem);
00055 
00056     
00057 
00058     
00059     void TraceAlloc(EMemAllocType type, void *memory, void *object, nuint objectSize, nsint count, const char *file, int line, const char *name);
00060     EMemAllocType TraceFree(EMemAllocType type, volatile void *object, char *&outAllocMem, nsint *outObjectSize, nsint *outCount, const char *file, int line);
00061 
00062     
00063     void InternalInitialize();
00064     void InternalShutdown();
00065 
00066 #ifndef MEMMAN_TRACING // -- if NOT using management --
00067     
00068     inline bool IsPointerAnObject(void *p)
00069         { return true; }
00070 
00071     
00072     inline void CheckForPaddingCorruption() {}
00073 #endif
00074 
00075 #ifdef MEMMAN_TRACING // -- if using management --
00076 
00077     
00078     bool IsPointerAnObject(void *p);
00079 
00080     
00081     void CheckForPaddingCorruption();
00082 
00083     struct SAlloc
00084     {
00085         EMemAllocType type;
00086         void *objAddr; 
00087         void *allocMem; 
00088         nuint size;
00089         std::string srcFile;
00090         int srcLine;
00091         nsint count; 
00092         std::string allocStack;
00093         std::string deleteStack;
00094         std::string name;
00095         bool countsAsLeak; 
00096 
00097         SAlloc *next;
00098 
00099         std::string Describe();
00100     };
00101 
00102 private:
00103     bool m_critErrors; 
00104 
00105     SAlloc *m_head; 
00106 
00107     
00108     bool VerifyAllocPadding(uint8 *mem, nuint objSize);
00109 
00110     
00111     struct SMapAllocDifference
00112     {
00113         void *actual;
00114         void *returned;
00115     };
00116     std::list<SMapAllocDifference> allocDifferences;
00117 
00118 #endif // -- end if using management --
00119 
00120     
00121     void ReportLeak(const std::string &leak);
00122 
00123     bool m_ready; 
00124 
00125 public: 
00126 #ifdef MEMMAN_TRACING // -- if using management --
00127     
00128     template <typename T> static void dbgN2_Destruct(T *obj)
00129     {
00130         obj->~T();
00131     }
00132     template <typename T> static void dbgN2_Destruct_array(T *obj, nsint count)
00133     {
00134         for (nsint i=0; i<count; ++i)
00135         {
00136             obj->~T();
00137             ++obj;
00138         }
00139     }
00140 
00141     
00142     template <typename T> static T dbgN3_ReturnNew(T obj)
00143     {
00144         AllocDifferenceMapEnd(obj);
00145         return obj;
00146     }
00147 
00148     static void AllocDifferenceMapStart(void *mem);
00149     static void AllocDifferenceMapEnd(void *mem);
00150 
00151     static void* DeallocDifferenceMap(void *mem, bool pop);
00152 #endif // -- end if using management --
00153 
00154     MPMAMemoryManager();
00155     ~MPMAMemoryManager();
00156 
00157 };
00158 
00159 extern MPMAMemoryManager mpmaMemoryManager;
00160 
00161 #ifndef MEMMAN_TRACING // -- if NOT using management --
00162 inline void MPMAMemoryManager::MarkAsIntentionallyLeaked(void *mem) {}
00163 #endif
00164 
00165 #ifdef MEMMAN_TRACING // -- if using management --
00166 
00167 
00168 #define dbgN2_padding 8
00169 
00170 
00171 void* operator new(size_t objLen, MPMAMemoryManager *theMan, const char *file, int line, const char *name);
00172 
00173 #define new3(obj)       MPMAMemoryManager::dbgN3_ReturnNew(new (&mpmaMemoryManager, __FILE__, __LINE__, ""#obj) obj)
00174 #define new2(obj, junk) new3(obj)
00175 
00176 void* operator new[](size_t objLen, MPMAMemoryManager *theMan, size_t count, const char *file, int line, const char *name);
00177 
00178 #define new3_array(obj, count)       MPMAMemoryManager::dbgN3_ReturnNew(new (&mpmaMemoryManager, count, __FILE__, __LINE__, ""#obj) obj[count])
00179 #define new2_array(obj, count, junk) new3_array(obj, count)
00180 
00181 
00182 
00183 void operator delete(void *obj, MPMAMemoryManager *theMan, const char *file, int line, const char *name);
00184 
00185 void operator delete[](void *obj, MPMAMemoryManager *theMan, size_t count, const char *file, int line, const char *name);
00186 
00187 #define delete3(obj) \
00188 do { \
00189     void *pObj=(void*)(obj); \
00190     nsint count=0; \
00191     nsint objSize=0; \
00192     char *realMem=0; \
00193     EMemAllocType type=mpmaMemoryManager.TraceFree(EMAT_One, pObj, realMem, &objSize, &count, __FILE__, __LINE__); \
00194     if (type==EMAT_One) MPMAMemoryManager::dbgN2_Destruct(obj); \
00195     else if (type==EMAT_Array) MPMAMemoryManager::dbgN2_Destruct_array(obj, count); \
00196     memset(pObj, 0x7e, objSize); \
00197     delete[] realMem; \
00198     *((nuint**)&obj)=(nuint*)-1; \
00199 } while(false)
00200 
00201 #define delete2(obj) delete3(obj) 
00202 
00203 #define delete3_array(obj) \
00204 do { \
00205     void *pObj=(void*)(obj); \
00206     nsint count=0; \
00207     nsint objSize=0; \
00208     char *realMem=0; \
00209     EMemAllocType type=mpmaMemoryManager.TraceFree(EMAT_Array, pObj, realMem, &objSize, &count, __FILE__, __LINE__); \
00210     if (type==EMAT_One) MPMAMemoryManager::dbgN2_Destruct(obj); \
00211     else if (type==EMAT_Array) MPMAMemoryManager::dbgN2_Destruct_array(obj, count); \
00212     memset(pObj, 0x7e, objSize); \
00213     delete[] realMem; \
00214     *((nuint**)&obj)=(nuint*)-1; \
00215 } while(false)
00216 
00217 #define delete2_array(obj) delete3_array(obj)
00218 
00219 #else // -- if NOT using management --
00220 
00221     #define new3(obj) new obj
00222     #define new2(obj,junk) new obj
00223     #define new3_array(obj,count) new obj[count]
00224     #define new2_array(obj,count,junk) new obj[count]
00225 
00226     #define delete3(obj) delete obj
00227     #define delete2(obj) delete obj
00228     #define delete3_array(obj) delete[] obj
00229     #define delete2_array(obj) delete[] obj
00230 
00231 #endif // -- end if using management --
00232 
00233 
00234 
00235 
00236 namespace MPMA
00237 {
00239     template <typename T>
00240     class AutoDelete
00241     {
00242     public:
00243         inline AutoDelete(T *inPtr): ptr(inPtr) {}
00244         inline ~AutoDelete() {if (ptr) delete2(ptr);}
00245     private:
00246         T *ptr;
00247     };
00248 
00250     template <typename T>
00251     class AutoDeleteArray
00252     {
00253     public:
00254         inline AutoDeleteArray(T *inPtr): ptr(inPtr) {}
00255         inline ~AutoDeleteArray() {if (ptr) delete2_array(ptr);}
00256     private:
00257         T *ptr;
00258     };
00259 }