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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include <stdlib.h>
00061 #include <errno.h>
00062
00063 #include "MemCheck.h"
00064 #include "TObjectTable.h"
00065 #include "TError.h"
00066 #include "TMapFile.h"
00067 #include "TSystem.h"
00068 #include "mmalloc.h"
00069
00070 void *CustomReAlloc1(void *ovp, size_t size);
00071 void *CustomReAlloc2(void *ovp, size_t size, size_t oldsize);
00072
00073 class TReAllocInit {
00074 public:
00075 TReAllocInit() { TStorage::SetReAllocHooks(&CustomReAlloc1, &CustomReAlloc2); }
00076 };
00077 static TReAllocInit gReallocInit;
00078
00079
00080
00081
00082 #if !defined(R__NOSTATS)
00083 # define MEM_DEBUG
00084 # define MEM_STAT
00085 # define MEM_CHECKOBJECTPOINTERS
00086 #endif
00087
00088 #if defined(MEM_STAT) && !defined(MEM_DEBUG)
00089 # define MEM_DEBUG
00090 #endif
00091
00092 #ifdef MEM_DEBUG
00093 # define MEM_MAGIC ((unsigned char)0xAB)
00094 #ifdef R__B64
00095 # define storage_size(p) ((size_t)(((size_t*)p)[-1]))
00096 # define RealStart(p) ((char*)(p) - sizeof(size_t))
00097 # define StoreSize(p, sz) (*((size_t*)(p)) = (sz))
00098 # define ExtStart(p) ((char*)(p) + sizeof(size_t))
00099 # define RealSize(sz) ((sz) + sizeof(size_t) + sizeof(char))
00100 # define StoreMagic(p, sz) *((unsigned char*)(p)+sz+sizeof(size_t)) = MEM_MAGIC
00101 #else
00102 # define storage_size(p) ((size_t)(((int*)p)[-2]))
00103 # define RealStart(p) ((char*)(p) - 2*sizeof(int))
00104 # define StoreSize(p, sz) (*((int*)(p)) = (sz))
00105 # define ExtStart(p) ((char*)(p) + 2*sizeof(int))
00106 # define RealSize(sz) ((sz) + 2*sizeof(int) + sizeof(char))
00107 # define StoreMagic(p, sz) *((unsigned char*)(p)+sz+2*sizeof(int)) = MEM_MAGIC
00108 #endif
00109 # define MemClear(p, start, len) \
00110 if ((len) > 0) memset(&((char*)(p))[(start)], 0, (len))
00111 # define TestMagic(p, sz) (*((unsigned char*)(p)+sz) != MEM_MAGIC)
00112 # define CheckMagic(p, s, where) \
00113 if (TestMagic(p, s)) \
00114 Fatal(where, "%s", "storage area overwritten");
00115 # define CheckFreeSize(p, where) \
00116 if (storage_size((p)) > TStorage::GetMaxBlockSize()) \
00117 Fatal(where, "unreasonable size (%ld)", (Long_t)storage_size(p));
00118 # define RemoveStatMagic(p, where) \
00119 CheckFreeSize(p, where); \
00120 RemoveStat(p); \
00121 CheckMagic(p, storage_size(p), where)
00122 # define StoreSizeMagic(p, size, where) \
00123 StoreSize(p, size); \
00124 StoreMagic(p, size); \
00125 EnterStat(size, ExtStart(p)); \
00126 CheckObjPtr(ExtStart(p), where);
00127 #else
00128 # define storage_size(p) ((size_t)0)
00129 # define RealSize(sz) (sz)
00130 # define RealStart(p) (p)
00131 # define ExtStart(p) (p)
00132 # define MemClear(p, start, len)
00133 # define StoreSizeMagic(p, size, where) \
00134 EnterStat(size, ExtStart(p)); \
00135 CheckObjPtr(ExtStart(p), where);
00136 # define RemoveStatMagic(p, where) \
00137 RemoveStat(p);
00138 #endif
00139
00140 #define MemClearRe(p, start, len) \
00141 if ((len) > 0) memset(&((char*)(p))[(start)], 0, (len))
00142
00143 #define CallFreeHook(p, size) \
00144 if (TStorage::GetFreeHook()) TStorage::GetFreeHook()(TStorage::GetFreeHookData(), (p), (size))
00145
00146 #ifdef MEM_CHECKOBJECTPOINTERS
00147
00148 # define CheckObjPtr(p, name)
00149 #else
00150 # define CheckObjPtr(p, name)
00151 #endif
00152
00153
00154 #ifdef MEM_STAT
00155
00156 #define EnterStat(s, p) \
00157 TStorage::EnterStat(s, p)
00158 #define RemoveStat(p) \
00159 TStorage::RemoveStat(p)
00160
00161 #else
00162
00163 #define EnterStat(s, p) \
00164 TStorage::SetMaxBlockSize(TMath::Max(TStorage::GetMaxBlockSize(), s))
00165 #define RemoveStat(p)
00166
00167 #endif
00168
00169
00170
00171 #ifdef __GNUC__
00172 # if !defined(R__THROWNEWDELETE) && __GNUC__ >= 3
00173 # define R__THROWNEWDELETE
00174 # endif
00175 #endif
00176
00177 #ifdef R__THROWNEWDELETE
00178 # ifdef R__OLDHPACC
00179 # define R__THROW_BAD throw(bad_alloc)
00180 # else
00181 # define R__THROW_BAD throw(std::bad_alloc)
00182 # endif
00183 # define R__THROW_NULL throw()
00184 #else
00185 # define R__THROW_BAD
00186 # define R__THROW_NULL
00187 #endif
00188
00189 static const char *gSpaceErr = "storage exhausted (failed to allocate %ld bytes)";
00190 static int gNewInit = 0;
00191
00192
00193 void *operator new(size_t size) R__THROW_BAD
00194 {
00195
00196
00197
00198 if (TROOT::MemCheck())
00199 return TMemHashTable::AddPointer(size);
00200
00201 static const char *where = "operator new";
00202
00203 if (!gNewInit) {
00204 TStorage::SetCustomNewDelete();
00205 gNewInit++;
00206 }
00207
00208 register void *vp;
00209 if (gMmallocDesc)
00210 vp = ::mcalloc(gMmallocDesc, RealSize(size), sizeof(char));
00211 else
00212 vp = ::calloc(RealSize(size), sizeof(char));
00213 if (vp == 0)
00214 Fatal(where, gSpaceErr, RealSize(size));
00215 StoreSizeMagic(vp, size, where);
00216 return ExtStart(vp);
00217 }
00218
00219 #ifndef R__PLACEMENTINLINE
00220
00221 void *operator new(size_t size, void *vp) R__THROW_NULL
00222 {
00223
00224
00225 static const char *where = "operator new(void *at)";
00226
00227 if (!gNewInit) {
00228 TStorage::SetCustomNewDelete();
00229 gNewInit++;
00230 }
00231
00232 if (vp == 0) {
00233
00234 if (TROOT::MemCheck())
00235 return TMemHashTable::AddPointer(size);
00236
00237 register void *vp;
00238 if (gMmallocDesc)
00239 vp = ::mcalloc(gMmallocDesc, RealSize(size), sizeof(char));
00240 else
00241 vp = ::calloc(RealSize(size), sizeof(char));
00242 if (vp == 0)
00243 Fatal(where, gSpaceErr, RealSize(size));
00244 StoreSizeMagic(vp, size, where);
00245 return ExtStart(vp);
00246 }
00247 return vp;
00248 }
00249 #endif
00250
00251
00252 void operator delete(void *ptr) R__THROW_NULL
00253 {
00254
00255
00256
00257 if (TROOT::MemCheck()) {
00258 TMemHashTable::FreePointer(ptr);
00259 return;
00260 }
00261
00262 static const char *where = "operator delete";
00263
00264 if (!gNewInit)
00265 Fatal(where, "space was not allocated via custom new");
00266
00267 if (ptr) {
00268 CheckObjPtr(ptr, where);
00269 CallFreeHook(ptr, storage_size(ptr));
00270 RemoveStatMagic(ptr, where);
00271 MemClear(RealStart(ptr), 0, RealSize(storage_size(ptr)));
00272 TSystem::ResetErrno();
00273 TMapFile *mf = TMapFile::WhichMapFile(RealStart(ptr));
00274 if (mf) {
00275 if (mf->IsWritable()) ::mfree(mf->GetMmallocDesc(), RealStart(ptr));
00276 } else {
00277 do {
00278 TSystem::ResetErrno();
00279 ::free(RealStart(ptr));
00280 } while (TSystem::GetErrno() == EINTR);
00281 }
00282 if (TSystem::GetErrno() != 0)
00283 SysError(where, "free");
00284 }
00285 }
00286
00287 #ifdef R__VECNEWDELETE
00288
00289 void *operator new[](size_t size) R__THROW_BAD
00290 {
00291
00292
00293 return ::operator new(size);
00294 }
00295
00296 #ifndef R__PLACEMENTINLINE
00297
00298 void *operator new[](size_t size, void *vp) R__THROW_NULL
00299 {
00300
00301
00302 return ::operator new(size, vp);
00303 }
00304 #endif
00305
00306
00307 void operator delete[](void *ptr) R__THROW_NULL
00308 {
00309 ::operator delete(ptr);
00310 }
00311 #endif
00312
00313
00314 void *CustomReAlloc1(void *ovp, size_t size)
00315 {
00316
00317
00318
00319 if (TROOT::MemCheck())
00320 return TMemHashTable::AddPointer(size, ovp);
00321
00322 static const char *where = "CustomReAlloc1";
00323
00324 if (ovp == 0)
00325 return ::operator new(size);
00326
00327 if (!gNewInit)
00328 Fatal(where, "space was not allocated via custom new");
00329
00330 size_t oldsize = storage_size(ovp);
00331 if (oldsize == size)
00332 return ovp;
00333 RemoveStatMagic(ovp, where);
00334 void *vp;
00335 if (gMmallocDesc)
00336 vp = ::mrealloc(gMmallocDesc, RealStart(ovp), RealSize(size));
00337 else
00338 vp = ::realloc((char*)RealStart(ovp), RealSize(size));
00339 if (vp == 0)
00340 Fatal(where, gSpaceErr, RealSize(size));
00341 if (size > oldsize)
00342 MemClearRe(ExtStart(vp), oldsize, size-oldsize);
00343
00344 StoreSizeMagic(vp, size, where);
00345 return ExtStart(vp);
00346 }
00347
00348
00349 void *CustomReAlloc2(void *ovp, size_t size, size_t oldsize)
00350 {
00351
00352
00353
00354
00355 if (TROOT::MemCheck())
00356 return TMemHashTable::AddPointer(size, ovp);
00357
00358 static const char *where = "CustomReAlloc2";
00359
00360 if (ovp == 0)
00361 return ::operator new(size);
00362
00363 if (!gNewInit)
00364 Fatal(where, "space was not allocated via custom new");
00365
00366 #if defined(MEM_DEBUG)
00367 if (oldsize != storage_size(ovp))
00368 fprintf(stderr, "<%s>: passed oldsize %u, should be %u\n", where,
00369 (unsigned int)oldsize, (unsigned int)storage_size(ovp));
00370 #endif
00371 if (oldsize == size)
00372 return ovp;
00373 RemoveStatMagic(ovp, where);
00374 void *vp;
00375 if (gMmallocDesc)
00376 vp = ::mrealloc(gMmallocDesc, RealStart(ovp), RealSize(size));
00377 else
00378 vp = ::realloc((char*)RealStart(ovp), RealSize(size));
00379 if (vp == 0)
00380 Fatal(where, gSpaceErr, RealSize(size));
00381 if (size > oldsize)
00382 MemClearRe(ExtStart(vp), oldsize, size-oldsize);
00383
00384 StoreSizeMagic(vp, size, where);
00385 return ExtStart(vp);
00386 }