00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _BASE_MEMORYTRACER_
00026 #define _BASE_MEMORYTRACER_
00027
00028 #include <base/base>
00029 #include <string>
00030
00031
00032 namespace base {
00033
00034
00035
00036 #ifdef DEBUG
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define _NAMEDOUTPUTONLY_
00047
00048
00049
00050
00051 #define _FULLINTEGRITYCHECK_ 1
00052
00053
00054
00055
00056 #define _FULLCHECKFREQUENTY_ 100
00057
00058
00059 #endif
00060
00061
00062
00063
00064 class MemoryTracer
00065 {
00066 public:
00067 static void* allocate(int size, const std::string& name, bool isArray=false) throw(std::bad_alloc);
00068 static bool release(void* address, bool isArray=false, int size = -1) throw(std::bad_alloc);
00069 static bool validate(void *address, int size, const std::string& name) throw(std::bad_alloc);
00070 static bool invalidate(void* address, int size) throw(std::bad_alloc);
00071
00072 static void* checkAddrRange(void* address, long typesize) throw(std::bad_alloc);
00073 static bool checkAddr(void* address, void* reportAddr = 0, bool checkAllMemory = true) throw(std::bad_alloc);
00074 static bool checkAllMemory() throw(std::bad_alloc);
00075
00076 static char* getName(void* addr);
00077 static long getOffset(void* addr);
00078
00079 static bool cleanup();
00080 static void menu() throw(std::bad_alloc);
00081 static void dump() ;
00082 static void dumpNamed();
00083 static void dumpDeallocated();
00084 static void handleError() throw(std::bad_alloc);
00085
00086 protected:
00087 static void Logerr(char* errstr);
00088 static void entrylock();
00089 static void exitunlock();
00090 static int causefault();
00091 static void fill()
00092 {
00093 for(Int i=0; i<Filling; i++)
00094 prefill[i] = postfill[i] = Filler;
00095 }
00096
00097 static bool isOK()
00098 {
00099 if (initialized != (Byte)Magic) {
00100 initialized = (Byte)Magic;
00101 fill();
00102 return true;
00103 }
00104 #ifdef _FULLINTEGRITYCHECK_
00105 for(Int i=0; i<Filling; i++)
00106 if ((prefill[i] != Filler) || (postfill[i] != Filler)) return false;
00107 #endif
00108 return true;
00109 }
00110
00111 static const Byte Filling = 8;
00112 static const Byte Filler = 0xea;
00113 static const int Magic = 13456;
00114 static const int External = 32768;
00115
00116 static const int IsArray;
00117 static const int IsNotArray;
00118
00119 struct AllocEntry {
00120 bool isExternal() const { return (magic & External); }
00121 void setExternal() { magic = (External | Magic); }
00122 void clearExternal() { magic = Magic; }
00123 void setMagic() { magic = Magic; }
00124 bool isMagic() const { return ((magic&Magic) == Magic); }
00125 bool isNotMagic() const { return !isMagic(); }
00126
00127 void fill()
00128 {
00129 for(Int i=0; i<Filling; i++)
00130 prefill[i] = postfill[i] = Filler;
00131 }
00132
00133 bool isOK() const
00134 {
00135 #ifdef _FULLINTEGRITYCHECK_
00136 for(Int i=0; i<Filling; i++)
00137 if ((prefill[i] != Filler) || (postfill[i] != Filler)) return false;
00138 if ((arrayFlag != MemoryTracer::IsArray) && (arrayFlag != MemoryTracer::IsNotArray)) return false;
00139 #endif
00140 if (size<=0) return false;
00141 if (isNotMagic()) return false;
00142 return true;
00143 }
00144
00145 bool isArray() { return arrayFlag == MemoryTracer::IsArray; }
00146 void setIsArray(bool isAnArray) { arrayFlag = isAnArray?MemoryTracer::IsArray:MemoryTracer::IsNotArray; }
00147
00148 Byte prefill[Filling];
00149 int size;
00150 Byte* address;
00151 int arrayFlag;
00152 char* name;
00153 int magic;
00154
00155 AllocEntry* prev;
00156 AllocEntry* next;
00157
00158 Byte postfill[Filling];
00159 };
00160
00161
00162 class AllocList
00163 {
00164 public:
00165 void push_front(AllocEntry* e);
00166 void push_back(AllocEntry* e);
00167 AllocEntry* pop_back();
00168 AllocEntry* pop_front();
00169 void remove(AllocEntry* e);
00170
00171 AllocEntry* front() const { return head; }
00172 AllocEntry* back() const { return tail; }
00173 int size() const { return len; }
00174
00175 AllocEntry* find(void* address, AllocEntry* from = 0) const;
00176
00177 protected:
00178
00179
00180
00181 AllocEntry* head;
00182 AllocEntry* tail;
00183 Int len;
00184 };
00185
00186 static const int DList_Max = 1000;
00187
00188 static Byte prefill[Filling];
00189
00190 static Byte initialized;
00191 static bool cleanedUp;
00192 static Int entry;
00193 static Int fullCheckCounter;
00194 static LInt allocCount;
00195 static LInt deallocCount;
00196 static LInt checkCount;
00197
00198 static AllocList mlist;
00199 static AllocList dlist;
00200
00201 static Byte postfill[Filling];
00202 };
00203
00204
00205 void stressTestAllocator();
00206
00207
00208 }
00209
00210
00211
00212 #ifdef _TRACEMEMORY_
00213 void* operator new(size_t size) throw (std::bad_alloc);
00214 void* operator new[](size_t size) throw (std::bad_alloc);
00215 void* operator new(size_t size, const std::string& name) throw (std::bad_alloc);
00216 void* operator new[](size_t size, const std::string& name) throw (std::bad_alloc);
00217 void operator delete(void* p) throw();
00218 void operator delete[](void* p) throw();
00219
00220
00221
00222 #define NewObj new
00223 #define NewNamedObj(name) new
00224 #define DeleteObj delete
00225
00226 #else
00227
00228 inline void* operator new(size_t size, const std::string& name) throw (std::bad_alloc)
00229 { return ::operator new(size); }
00230 inline void* operator new[](size_t size, const std::string& name) throw (std::bad_alloc)
00231 { return ::operator new[](size); }
00232
00233 #define NewObj new
00234 #define NewNamedObj(name) new
00235 #define DeleteObj delete
00236
00237 #endif
00238
00239
00240
00241 #endif
00242