Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 = nullptr;
85 gMemSize = -1, gMemIndex = -1;
86
87// Used in NewDelete.cxx; set by TMapFile.
89void *ROOT::Internal::gMmallocDesc = nullptr; //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]++;
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] = nullptr;
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
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 == nullptr)
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 == nullptr) {
204 Fatal(where, "%s", gSpaceErr);
205 return nullptr; // Unreachable unless gErrorIgnoreLevel > kFatal.
206 }
207
208 if (ovp == nullptr)
209 return vp;
210
211 memmove(vp, ovp, size);
212#ifndef WIN32
213 ::operator delete[](ovp);
214#else
215 ::operator delete(ovp);
216#endif
217 return vp;
218}
219
220////////////////////////////////////////////////////////////////////////////////
221/// Reallocate (i.e. resize) block of memory. Checks if current size is
222/// equal to oldsize. If not memory was overwritten.
223
224void *TStorage::ReAlloc(void *ovp, size_t size, size_t oldsize)
225{
226 // Needs to be protected by global mutex
227 {
229
231 return (*fgReAllocCHook)(ovp, size, oldsize);
232 }
233
234 static const char *where = "TStorage::ReAlloc";
235
236 if (oldsize == size)
237 return ovp;
238
239#ifndef WIN32
240 void *vp = ::operator new[](size);
241#else
242 void *vp = ::operator new(size);
243#endif
244 if (vp == nullptr) {
245 Fatal(where, "%s", gSpaceErr);
246 return nullptr; // Unreachable unless gErrorIgnoreLevel > kFatal.
247 }
248
249 if (ovp == nullptr)
250 return vp;
251
252 if (size > oldsize) {
253 memcpy(vp, ovp, oldsize);
254 memset((char*)vp+oldsize, 0, size-oldsize);
255 } else
256 memcpy(vp, ovp, size);
257#ifndef WIN32
258 ::operator delete[](ovp);
259#else
260 ::operator delete(ovp);
261#endif
262 return vp;
263}
264
265////////////////////////////////////////////////////////////////////////////////
266/// Reallocate (i.e. resize) array of chars. Size and oldsize are
267/// in number of chars.
268
269char *TStorage::ReAllocChar(char *ovp, size_t size, size_t oldsize)
270{
271 static const char *where = "TStorage::ReAllocChar";
272
273 char *vp;
274 if (ovp == nullptr) {
275 vp = new char[size];
276 if (vp == nullptr)
277 Fatal(where, "%s", gSpaceErr);
278 return vp;
279 }
280 if (oldsize == size)
281 return ovp;
282
283 vp = new char[size];
284 if (vp == nullptr)
285 Fatal(where, "%s", gSpaceErr);
286 if (size > oldsize) {
287 memcpy(vp, ovp, oldsize);
288 memset((char*)vp+oldsize, 0, size-oldsize);
289 } else
290 memcpy(vp, ovp, size);
291 delete [] ovp;
292 return vp;
293}
294
295////////////////////////////////////////////////////////////////////////////////
296/// Reallocate (i.e. resize) array of integers. Size and oldsize are
297/// number of integers (not number of bytes).
298
299Int_t *TStorage::ReAllocInt(Int_t *ovp, size_t size, size_t oldsize)
300{
301 static const char *where = "TStorage::ReAllocInt";
302
303 Int_t *vp;
304 if (ovp == nullptr) {
305 vp = new Int_t[size];
306 if (vp == nullptr)
307 Fatal(where, "%s", gSpaceErr);
308 return vp;
309 }
310 if (oldsize == size)
311 return ovp;
312
313 vp = new Int_t[size];
314 if (vp == nullptr)
315 Fatal(where, "%s", gSpaceErr);
316 if (size > oldsize) {
317 memcpy(vp, ovp, oldsize*sizeof(Int_t));
318 memset((Int_t*)vp+oldsize, 0, (size-oldsize)*sizeof(Int_t));
319 } else
320 memcpy(vp, ovp, size*sizeof(Int_t));
321 delete [] ovp;
322 return vp;
323}
324
325////////////////////////////////////////////////////////////////////////////////
326/// Used to allocate a TObject on the heap (via TObject::operator new()).
327/// Directly after this routine one can call (in the TObject ctor)
328/// TStorage::FilledByObjectAlloc() to find out if the just created object is on
329/// the heap. This technique is necessary as there is one stack per thread
330/// and we can not rely on comparison with the current stack memory position.
331
332void *TStorage::ObjectAlloc(size_t sz)
333{
334 void* space = ::operator new(sz);
335 memset(space, kObjectAllocMemValue, sz);
336 return space;
337}
338
339////////////////////////////////////////////////////////////////////////////////
340/// Used to allocate array of TObject on the heap (via TObject::operator new[]()).
341/// Unlike the 'singular' ObjectAlloc, we do not mark those object has being
342/// allocated on the heap as they can not be individually deleted.
343
345{
346 void* space = ::operator new(sz);
347 return space;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Used to allocate a TObject on the heap (via TObject::operator new(size_t,void*))
352/// in position vp. vp is already allocated (maybe on heap, maybe on
353/// stack) so just return.
354
355void *TStorage::ObjectAlloc(size_t , void *vp)
356{
357 return vp;
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Used to deallocate a TObject on the heap (via TObject::operator delete()).
362
364{
365
366 ::operator delete(vp);
367}
368
369////////////////////////////////////////////////////////////////////////////////
370/// Used to deallocate a TObject on the heap (via TObject::operator delete(void*,void*)).
371
372void TStorage::ObjectDealloc(void *vp, void *ptr)
373{
374 if (vp && ptr) { }
375}
376
377#ifdef R__SIZEDDELETE
378////////////////////////////////////////////////////////////////////////////////
379/// Used to deallocate a TObject on the heap (via TObject::operator delete()),
380/// for sized deallocation.
381
382void TStorage::ObjectDealloc(void *vp, size_t size)
383{
384 ::operator delete(vp, size);
385}
386#endif
387
388////////////////////////////////////////////////////////////////////////////////
389/// Set a free handler.
390
392{
393 fgFreeHook = fh;
395}
396
397////////////////////////////////////////////////////////////////////////////////
398/// Set a custom ReAlloc handlers. This function is typically
399/// called via a static object in the ROOT libNew.so shared library.
400
402{
403 fgReAllocHook = rh1;
404 fgReAllocCHook = rh2;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408/// Print memory usage statistics.
409
411{
412 // Needs to be protected by global mutex
414
415#if defined(MEM_DEBUG) && defined(MEM_STAT)
416
418 return;
419
420 //Printf("");
421 Printf("Heap statistics");
422 Printf("%12s%12s%12s%12s", "size", "alloc", "free", "diff");
423 Printf("================================================");
424
425 int i;
426 for (i = 0; i < (int)kObjMaxSize; i++)
427 if (gAllocated[i] != gFreed[i])
428 //if (gAllocated[i])
429 Printf("%12d%12d%12d%12d", i, gAllocated[i], gFreed[i],
430 gAllocated[i]-gFreed[i]);
431
433 Printf("------------------------------------------------");
434 Printf("Total: %12d%12d%12d", gAllocatedTotal, gFreedTotal,
436 }
437
438 if (gMemSize != -1) {
439 Printf("------------------------------------------------");
440 for (i= 0; i < gTraceIndex; i++)
441 if (gTraceArray[i])
442 Printf("block %d of size %d not freed", i, gMemSize);
443 }
444 Printf("================================================");
445 Printf(" ");
446#endif
447}
448
449////////////////////////////////////////////////////////////////////////////////
450/// Enable memory usage statistics gathering. Size is the size of the memory
451/// block that should be trapped and ix is after how many such allocations
452/// the trap should happen.
453
455{
456#ifdef MEM_STAT
457 gMemSize = size;
458 gMemIndex = ix;
460#else
461 int idum = size; int iidum = ix;
462#endif
463}
464
465////////////////////////////////////////////////////////////////////////////////
466
468{
469 ::Obsolete("GetHeapBegin()", "v5-34-00", "v6-02-00");
470 //return begin of heap
471 return 0;
472}
473
474////////////////////////////////////////////////////////////////////////////////
475
477{
478 ::Obsolete("GetHeapBegin()", "v5-34-00", "v6-02-00");
479 //return end of heap
480 return 0;
481}
482
483////////////////////////////////////////////////////////////////////////////////
484///return static free hook data
485
487{
488 return fgFreeHookData;
489}
490
491////////////////////////////////////////////////////////////////////////////////
492///return the has custom delete flag
493
495{
497}
498
499////////////////////////////////////////////////////////////////////////////////
500///set the has custom delete flag
501
503{
505}
506
507
508////////////////////////////////////////////////////////////////////////////////
509///add a range to the heap
510
512{
513 ::Obsolete("AddToHeap(ULong_t,ULong_t)", "v5-34-00", "v6-02-00");
514}
515
516////////////////////////////////////////////////////////////////////////////////
517///is object at p in the heap?
518
520{
521 ::Obsolete("IsOnHeap(void*)", "v5-34-00", "v6-02-00");
522 return false;
523}
524
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
unsigned long ULong_t
Definition RtypesCore.h:55
#define ClassImp(name)
Definition Rtypes.h:377
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:230
void Obsolete(const char *function, const char *asOfVers, const char *removedFromVers)
Use this function to declare a function obsolete.
Definition TError.cxx:189
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:256
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2481
R__EXTERN TVirtualMutex * gGlobalMutex
#define R__LOCKGUARD(mutex)
#define realloc
Definition civetweb.c:1538
#define malloc
Definition civetweb.c:1536
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:269
static FreeHookFun_t fgFreeHook
Definition TStorage.h:37
static Bool_t HasCustomNewDelete()
return the has custom delete flag
Definition TStorage.cxx:494
static void EnterStat(size_t size, void *p)
Register a memory allocation operation.
Definition TStorage.cxx:99
static ULong_t GetHeapBegin()
Definition TStorage.cxx:467
static void ObjectDealloc(void *vp)
Used to deallocate a TObject on the heap (via TObject::operator delete()).
Definition TStorage.cxx:363
static void SetFreeHook(FreeHookFun_t func, void *data)
Set a free handler.
Definition TStorage.cxx:391
static void SetCustomNewDelete()
set the has custom delete flag
Definition TStorage.cxx:502
static void AddToHeap(ULong_t begin, ULong_t end)
add a range to the heap
Definition TStorage.cxx:511
static ULong_t GetHeapEnd()
Definition TStorage.cxx:476
static void * GetFreeHookData()
return static free hook data
Definition TStorage.cxx:486
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition TStorage.cxx:183
static void SetMaxBlockSize(size_t size)
Definition TStorage.h:141
static void * fgFreeHookData
Definition TStorage.h:38
static Bool_t IsOnHeap(void *p)
is object at p in the heap?
Definition TStorage.cxx:519
static const UInt_t kObjectAllocMemValue
Definition TStorage.h:49
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:299
static void SetReAllocHooks(ReAllocFun_t func1, ReAllocCFun_t func2)
Set a custom ReAlloc handlers.
Definition TStorage.cxx:401
static void * ObjectAllocArray(size_t size)
Used to allocate array of TObject on the heap (via TObject::operator new[]()).
Definition TStorage.cxx:344
static void EnableStatistics(int size=-1, int ix=-1)
Enable memory usage statistics gathering.
Definition TStorage.cxx:454
static ReAllocFun_t fgReAllocHook
Definition TStorage.h:39
static size_t GetMaxBlockSize()
Definition TStorage.h:139
static void * ObjectAlloc(size_t size)
Used to allocate a TObject on the heap (via TObject::operator new()).
Definition TStorage.cxx:332
static void PrintStatistics()
Print memory usage statistics.
Definition TStorage.cxx:410
R__EXTERN FreeIfTMapFile_t * gFreeIfTMapFile
Definition TStorage.h:148
R__EXTERN void * gMmallocDesc
Definition TStorage.h:149
bool(void *) FreeIfTMapFile_t
Definition TStorage.h:147
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250