00001
00002
00014
00015
00016
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>
00031 #include "Types.h"
00032 #include "Locks.h"
00033
00034
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
00053 inline bool IsReady() const
00054 { return m_ready; }
00055
00056
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
00061 void InternalInitialize();
00062 void InternalShutdown();
00063
00064 #ifndef MEMMAN_TRACING // -- if NOT using management --
00065
00066 inline bool IsPointerAnObject(void *p)
00067 { return true; }
00068
00069
00070 inline void CheckForPaddingCorruption() {}
00071 #endif
00072
00073 #ifdef MEMMAN_TRACING // -- if using management --
00074
00075
00076 bool IsPointerAnObject(void *p);
00077
00078
00079 void CheckForPaddingCorruption();
00080
00081 struct SAlloc
00082 {
00083 EMemAllocType type;
00084 void *objAddr;
00085 void *allocMem;
00086 uint size;
00087 std::string srcFile;
00088 int srcLine;
00089 int count;
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;
00100
00101 SAlloc *m_head;
00102
00103
00104 bool VerifyAllocPadding(uint8 *mem, uint objSize);
00105
00106
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
00118 void ReportLeak(const std::string &leak);
00119 std::list<void (*)(const std::string &)> leakCallbacks;
00120
00121 bool m_ready;
00122 MPMA::MutexLock *syncLock;
00123
00124 public:
00125 #ifdef MEMMAN_TRACING // -- if using management --
00126
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
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
00159 #define dbgN2_padding 8
00160
00161
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
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
00226
00227
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 };