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 }