Logo ROOT   6.16/01
Reference Guide
TStorage.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Fons Rademakers 29/07/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TStorage
13\ingroup Base
14
15Storage manager. The storage manager works best in conjunction with
16the custom ROOT new and delete operators defined in the file
17NewDelete.cxx (libNew.so). Only when using the custom allocation
18operators will memory usage statistics be gathered using the
19TStorage EnterStat(), RemoveStat(), etc. functions.
20Memory checking is by default enabled (when using libNew.so) and
21usage statistics is gathered. Using the resource (in .rootrc):
22Root.MemStat one can toggle statistics gathering on or off. More
23specifically on can trap the allocation of a block of memory of a
24certain size. This can be specified using the resource:
25Root.MemStat.size, using the resource Root.MemStat.cnt one can
26specify after how many allocations of this size the trap should
27occur.
28
29Set the compile option R__NOSTATS to de-activate all memory checking
30and statistics gathering in the system.
31*/
32
33#include <stdlib.h>
34
35#include "TROOT.h"
36#include "TObjectTable.h"
37#include "TError.h"
38#include "TString.h"
39#include "TVirtualMutex.h"
40#include "TInterpreter.h"
41
42#if !defined(R__NOSTATS)
43# define MEM_DEBUG
44# define MEM_STAT
45# define MEM_CHECKOBJECTPOINTERS
46#endif
47
48#if defined(MEM_STAT) && !defined(MEM_DEBUG)
49# define MEM_DEBUG
50#endif
51
52#ifdef MEM_DEBUG
53# ifdef R__B64
54# define storage_size(p) ((size_t)(((size_t*)p)[-1]))
55# else
56# define storage_size(p) ((size_t)(((int*)p)[-2]))
57# endif
58#else
59# define storage_size(p) ((size_t)0)
60#endif
61
62#define PVOID (-1)
63
70
71
73
74//------------------------------------------------------------------------------
75
76static const char *gSpaceErr = "storage exhausted";
77
78const size_t kObjMaxSize = 10024;
79
83static void **gTraceArray = 0;
85 gMemSize = -1, gMemIndex = -1;
86
87// Used in NewDelete.cxx; set by TMapFile.
89void *ROOT::Internal::gMmallocDesc = 0; //is used and set in TMapFile
90
91
92
93////////////////////////////////////////////////////////////////////////////////
94/// Register a memory allocation operation. If desired one can trap an
95/// allocation of a certain size in case one tries to find a memory
96/// leak of that particular size. This function is only called via
97/// the ROOT custom new operators.
98
99void TStorage::EnterStat(size_t size, void *p)
100{
102
103 if (!gMemStatistics) return;
104
105 if ((Int_t)size == gMemSize) {
106 if (gTraceIndex == gMemIndex)
107 Fatal("EnterStat", "trapped allocation %d", gMemIndex);
108
109 if (!gTraceArray)
110 gTraceArray = (void**) malloc(sizeof(void*)*gTraceCapacity);
111
114 gTraceArray = (void**) realloc(gTraceArray, sizeof(void*)*gTraceCapacity);
115 }
117 }
118 if (size >= kObjMaxSize)
120 else
121 gAllocated[size]++;
122 gAllocatedTotal += size;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// Register a memory free operation. This function is only called via
127/// the custom ROOT delete operator.
128
130{
131 if (!gMemStatistics) return;
132
133 size_t size = storage_size(vp);
134 if ((Int_t)size == gMemSize) {
135 for (int i = 0; i < gTraceIndex; i++)
136 if (gTraceArray[i] == vp) {
137 gTraceArray[i] = 0;
138 break;
139 }
140 }
141 if (size >= kObjMaxSize)
142 gFreed[kObjMaxSize-1]++;
143 else
144 gFreed[size]++;
145 gFreedTotal += size;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Allocate a block of memory, that later can be resized using
150/// TStorage::ReAlloc().
151
152void *TStorage::Alloc(size_t size)
153{
154 static const char *where = "TStorage::Alloc";
155
156#ifndef WIN32
157 void *vp = ::operator new[](size);
158#else
159 void *vp = ::operator new(size);
160#endif
161 if (vp == 0)
162 Fatal(where, "%s", gSpaceErr);
163
164 return vp;
165}
166
167////////////////////////////////////////////////////////////////////////////////
168/// De-allocate block of memory, that was allocated via TStorage::Alloc().
169
170void TStorage::Dealloc(void *ptr)
171{
172#ifndef WIN32
173 ::operator delete[](ptr);
174#else
175 ::operator delete(ptr);
176#endif
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Reallocate (i.e. resize) block of memory. Don't use if size is larger
181/// than old size, use ReAlloc(void *, size_t, size_t) instead.
182
183void *TStorage::ReAlloc(void *ovp, size_t size)
184{
185 ::Obsolete("ReAlloc(void*,size_t)", "v5-34-00", "v6-02-00");
186 ::Info("ReAlloc(void*,size_t)", "please use ReAlloc(void*,size_t,size_t)");
187
188 {
189 // Needs to be protected by global mutex
191
193 return (*fgReAllocHook)(ovp, size);
194 }
195
196 static const char *where = "TStorage::ReAlloc";
197
198#ifndef WIN32
199 void *vp = ::operator new[](size);
200#else
201 void *vp = ::operator new(size);
202#endif
203 if (vp == 0)
204 Fatal(where, "%s", gSpaceErr);
205
206 if (ovp == 0)
207 return vp;
208
209 memmove(vp, ovp, size);
210#ifndef WIN32
211 ::operator delete[](ovp);
212#else
213 ::operator delete(ovp);
214#endif
215 return vp;
216}
217
218////////////////////////////////////////////////////////////////////////////////
219/// Reallocate (i.e. resize) block of memory. Checks if current size is
220/// equal to oldsize. If not memory was overwritten.
221
222void *TStorage::ReAlloc(void *ovp, size_t size, size_t oldsize)
223{
224 // Needs to be protected by global mutex
225 {
227
229 return (*fgReAllocCHook)(ovp, size, oldsize);
230 }
231
232 static const char *where = "TStorage::ReAlloc";
233
234 if (oldsize == size)
235 return ovp;
236
237#ifndef WIN32
238 void *vp = ::operator new[](size);
239#else
240 void *vp = ::operator new(size);
241#endif
242 if (vp == 0)
243 Fatal(where, "%s", gSpaceErr);
244
245 if (ovp == 0)
246 return vp;
247
248 if (size > oldsize) {
249 memcpy(vp, ovp, oldsize);
250 memset((char*)vp+oldsize, 0, size-oldsize);
251 } else
252 memcpy(vp, ovp, size);
253#ifndef WIN32
254 ::operator delete[](ovp);
255#else
256 ::operator delete(ovp);
257#endif
258 return vp;
259}
260
261////////////////////////////////////////////////////////////////////////////////
262/// Reallocate (i.e. resize) array of chars. Size and oldsize are
263/// in number of chars.
264
265char *TStorage::ReAllocChar(char *ovp, size_t size, size_t oldsize)
266{
267 static const char *where = "TStorage::ReAllocChar";
268
269 char *vp;
270 if (ovp == 0) {
271 vp = new char[size];
272 if (vp == 0)
273 Fatal(where, "%s", gSpaceErr);
274 return vp;
275 }
276 if (oldsize == size)
277 return ovp;
278
279 vp = new char[size];
280 if (vp == 0)
281 Fatal(where, "%s", gSpaceErr);
282 if (size > oldsize) {
283 memcpy(vp, ovp, oldsize);
284 memset((char*)vp+oldsize, 0, size-oldsize);
285 } else
286 memcpy(vp, ovp, size);
287 delete [] ovp;
288 return vp;
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Reallocate (i.e. resize) array of integers. Size and oldsize are
293/// number of integers (not number of bytes).
294
295Int_t *TStorage::ReAllocInt(Int_t *ovp, size_t size, size_t oldsize)
296{
297 static const char *where = "TStorage::ReAllocInt";
298
299 Int_t *vp;
300 if (ovp == 0) {
301 vp = new Int_t[size];
302 if (vp == 0)
303 Fatal(where, "%s", gSpaceErr);
304 return vp;
305 }
306 if (oldsize == size)
307 return ovp;
308
309 vp = new Int_t[size];
310 if (vp == 0)
311 Fatal(where, "%s", gSpaceErr);
312 if (size > oldsize) {
313 memcpy(vp, ovp, oldsize*sizeof(Int_t));
314 memset((Int_t*)vp+oldsize, 0, (size-oldsize)*sizeof(Int_t));
315 } else
316 memcpy(vp, ovp, size*sizeof(Int_t));
317 delete [] ovp;
318 return vp;
319}
320
321////////////////////////////////////////////////////////////////////////////////
322/// Used to allocate a TObject on the heap (via TObject::operator new()).
323/// Directly after this routine one can call (in the TObject ctor)
324/// TStorage::FilledByObjectAlloc() to find out if the just created object is on
325/// the heap. This technique is necessary as there is one stack per thread
326/// and we can not rely on comparison with the current stack memory position.
327
328void *TStorage::ObjectAlloc(size_t sz)
329{
330 void* space = ::operator new(sz);
331 memset(space, kObjectAllocMemValue, sz);
332 return space;
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// Used to allocate array of TObject on the heap (via TObject::operator new[]()).
337/// Unlike the 'singular' ObjectAlloc, we do not mark those object has being
338/// allocated on the heap as they can not be individually deleted.
339
341{
342 void* space = ::operator new(sz);
343 return space;
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Used to allocate a TObject on the heap (via TObject::operator new(size_t,void*))
348/// in position vp. vp is already allocated (maybe on heap, maybe on
349/// stack) so just return.
350
351void *TStorage::ObjectAlloc(size_t , void *vp)
352{
353 return vp;
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Used to deallocate a TObject on the heap (via TObject::operator delete()).
358
360{
361
362 ::operator delete(vp);
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// Used to deallocate a TObject on the heap (via TObject::operator delete(void*,void*)).
367
368void TStorage::ObjectDealloc(void *vp, void *ptr)
369{
370 if (vp && ptr) { }
371}
372
373#ifdef R__SIZEDDELETE
374////////////////////////////////////////////////////////////////////////////////
375/// Used to deallocate a TObject on the heap (via TObject::operator delete()),
376/// for sized deallocation.
377
378void TStorage::ObjectDealloc(void *vp, size_t size)
379{
380 ::operator delete(vp, size);
381}
382#endif
383
384////////////////////////////////////////////////////////////////////////////////
385/// Set a free handler.
386
388{
389 fgFreeHook = fh;
391}
392
393////////////////////////////////////////////////////////////////////////////////
394/// Set a custom ReAlloc handlers. This function is typically
395/// called via a static object in the ROOT libNew.so shared library.
396
398{
399 fgReAllocHook = rh1;
400 fgReAllocCHook = rh2;
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Print memory usage statistics.
405
407{
408 // Needs to be protected by global mutex
410
411#if defined(MEM_DEBUG) && defined(MEM_STAT)
412
414 return;
415
416 //Printf("");
417 Printf("Heap statistics");
418 Printf("%12s%12s%12s%12s", "size", "alloc", "free", "diff");
419 Printf("================================================");
420
421 int i;
422 for (i = 0; i < (int)kObjMaxSize; i++)
423 if (gAllocated[i] != gFreed[i])
424 //if (gAllocated[i])
425 Printf("%12d%12d%12d%12d", i, gAllocated[i], gFreed[i],
426 gAllocated[i]-gFreed[i]);
427
429 Printf("------------------------------------------------");
430 Printf("Total: %12d%12d%12d", gAllocatedTotal, gFreedTotal,
432 }
433
434 if (gMemSize != -1) {
435 Printf("------------------------------------------------");
436 for (i= 0; i < gTraceIndex; i++)
437 if (gTraceArray[i])
438 Printf("block %d of size %d not freed", i, gMemSize);
439 }
440 Printf("================================================");
441 Printf(" ");
442#endif
443}
444
445////////////////////////////////////////////////////////////////////////////////
446/// Enable memory usage statistics gathering. Size is the size of the memory
447/// block that should be trapped and ix is after how many such allocations
448/// the trap should happen.
449
450void TStorage::EnableStatistics(int size, int ix)
451{
452#ifdef MEM_STAT
453 gMemSize = size;
454 gMemIndex = ix;
456#else
457 int idum = size; int iidum = ix;
458#endif
459}
460
461////////////////////////////////////////////////////////////////////////////////
462
464{
465 ::Obsolete("GetHeapBegin()", "v5-34-00", "v6-02-00");
466 //return begin of heap
467 return 0;
468}
469
470////////////////////////////////////////////////////////////////////////////////
471
473{
474 ::Obsolete("GetHeapBegin()", "v5-34-00", "v6-02-00");
475 //return end of heap
476 return 0;
477}
478
479////////////////////////////////////////////////////////////////////////////////
480///return static free hook data
481
483{
484 return fgFreeHookData;
485}
486
487////////////////////////////////////////////////////////////////////////////////
488///return the has custom delete flag
489
491{
493}
494
495////////////////////////////////////////////////////////////////////////////////
496///set the has custom delete flag
497
499{
501}
502
503
504////////////////////////////////////////////////////////////////////////////////
505///add a range to the heap
506
508{
509 ::Obsolete("AddToHeap(ULong_t,ULong_t)", "v5-34-00", "v6-02-00");
510}
511
512////////////////////////////////////////////////////////////////////////////////
513///is object at p in the heap?
514
516{
517 ::Obsolete("IsOnHeap(void*)", "v5-34-00", "v6-02-00");
518 return false;
519}
520
int Int_t
Definition: RtypesCore.h:41
unsigned long ULong_t
Definition: RtypesCore.h:51
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
void Info(const char *location, const char *msgfmt,...)
void Obsolete(const char *function, const char *asOfVers, const char *removedFromVers)
Use this function to declare a function obsolete.
Definition: TError.cxx:278
void Fatal(const char *location, const char *msgfmt,...)
#define Printf
Definition: TGeoToOCC.h:18
static Int_t gMemIndex
Definition: TStorage.cxx:85
static const char * gSpaceErr
Definition: TStorage.cxx:76
static Int_t gTraceCapacity
Definition: TStorage.cxx:84
static Int_t gTraceIndex
Definition: TStorage.cxx:84
static Bool_t gMemStatistics
Definition: TStorage.cxx:80
static Int_t gMemSize
Definition: TStorage.cxx:85
const size_t kObjMaxSize
Definition: TStorage.cxx:78
static Int_t gFreed[kObjMaxSize]
Definition: TStorage.cxx:81
static void ** gTraceArray
Definition: TStorage.cxx:83
static Int_t gAllocated[kObjMaxSize]
Definition: TStorage.cxx:81
static Int_t gAllocatedTotal
Definition: TStorage.cxx:82
#define storage_size(p)
Definition: TStorage.cxx:56
static Int_t gFreedTotal
Definition: TStorage.cxx:82
void *(* ReAllocCFun_t)(void *, size_t, size_t)
Definition: TStorage.h:29
void *(* ReAllocFun_t)(void *, size_t)
Definition: TStorage.h:28
void(* FreeHookFun_t)(void *, void *addr, size_t)
Definition: TStorage.h:27
R__EXTERN TVirtualMutex * gGlobalMutex
Definition: TVirtualMutex.h:29
#define R__LOCKGUARD(mutex)
#define realloc
Definition: civetweb.c:1538
#define malloc
Definition: civetweb.c:1536
static Bool_t MemCheck()
Return kTRUE if the memory leak checker is on.
Definition: TROOT.cxx:2867
Storage manager.
Definition: TStorage.h:33
static ReAllocCFun_t fgReAllocCHook
Definition: TStorage.h:40
static void RemoveStat(void *p)
Register a memory free operation.
Definition: TStorage.cxx:129
static void * Alloc(size_t size)
Allocate a block of memory, that later can be resized using TStorage::ReAlloc().
Definition: TStorage.cxx:152
static Bool_t fgHasCustomNewDelete
Definition: TStorage.h:41
static char * ReAllocChar(char *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:265
static FreeHookFun_t fgFreeHook
Definition: TStorage.h:37
static Bool_t HasCustomNewDelete()
return the has custom delete flag
Definition: TStorage.cxx:490
static void EnterStat(size_t size, void *p)
Register a memory allocation operation.
Definition: TStorage.cxx:99
static ULong_t GetHeapBegin()
Definition: TStorage.cxx:463
static void ObjectDealloc(void *vp)
Used to deallocate a TObject on the heap (via TObject::operator delete()).
Definition: TStorage.cxx:359
static void SetFreeHook(FreeHookFun_t func, void *data)
Set a free handler.
Definition: TStorage.cxx:387
static void SetCustomNewDelete()
set the has custom delete flag
Definition: TStorage.cxx:498
static void AddToHeap(ULong_t begin, ULong_t end)
add a range to the heap
Definition: TStorage.cxx:507
static ULong_t GetHeapEnd()
Definition: TStorage.cxx:472
static void * GetFreeHookData()
return static free hook data
Definition: TStorage.cxx:482
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
static void SetMaxBlockSize(size_t size)
Definition: TStorage.h:118
static void * fgFreeHookData
Definition: TStorage.h:38
static Bool_t IsOnHeap(void *p)
is object at p in the heap?
Definition: TStorage.cxx:515
static const UInt_t kObjectAllocMemValue
Definition: TStorage.h:43
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition: TStorage.cxx:170
static size_t fgMaxBlockSize
Definition: TStorage.h:36
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:295
static void SetReAllocHooks(ReAllocFun_t func1, ReAllocCFun_t func2)
Set a custom ReAlloc handlers.
Definition: TStorage.cxx:397
static void * ObjectAllocArray(size_t size)
Used to allocate array of TObject on the heap (via TObject::operator new[]()).
Definition: TStorage.cxx:340
static void EnableStatistics(int size=-1, int ix=-1)
Enable memory usage statistics gathering.
Definition: TStorage.cxx:450
static ReAllocFun_t fgReAllocHook
Definition: TStorage.h:39
static size_t GetMaxBlockSize()
Definition: TStorage.h:116
static void * ObjectAlloc(size_t size)
Used to allocate a TObject on the heap (via TObject::operator new()).
Definition: TStorage.cxx:328
static void PrintStatistics()
Print memory usage statistics.
Definition: TStorage.cxx:406
R__EXTERN FreeIfTMapFile_t * gFreeIfTMapFile
Definition: TStorage.h:125
R__EXTERN void * gMmallocDesc
Definition: TStorage.h:126
bool(void *) FreeIfTMapFile_t
Definition: TStorage.h:124
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212