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
69
70
72
73//------------------------------------------------------------------------------
74
75static const char *gSpaceErr = "storage exhausted";
76
77const size_t kObjMaxSize = 10024;
78
82static void **gTraceArray = nullptr;
84 gMemSize = -1, gMemIndex = -1;
85
86// Used in NewDelete.cxx; set by TMapFile.
88void *ROOT::Internal::gMmallocDesc = nullptr; //is used and set in TMapFile
89
90
91
92////////////////////////////////////////////////////////////////////////////////
93/// Register a memory allocation operation. If desired one can trap an
94/// allocation of a certain size in case one tries to find a memory
95/// leak of that particular size. This function is only called via
96/// the ROOT custom new operators.
97
98void TStorage::EnterStat(size_t size, void *p)
99{
101
102 if (!gMemStatistics) return;
103
104 if ((Int_t)size == gMemSize) {
105 if (gTraceIndex == gMemIndex)
106 Fatal("EnterStat", "trapped allocation %d", gMemIndex);
107
108 if (!gTraceArray)
109 gTraceArray = (void**) malloc(sizeof(void*)*gTraceCapacity);
110
113 gTraceArray = (void**) realloc(gTraceArray, sizeof(void*)*gTraceCapacity);
114 }
116 }
117 if (size >= kObjMaxSize)
119 else
120 gAllocated[size]++;
122}
123
124////////////////////////////////////////////////////////////////////////////////
125/// Register a memory free operation. This function is only called via
126/// the custom ROOT delete operator.
127
129{
130 if (!gMemStatistics) return;
131
132 size_t size = storage_size(vp);
133 if ((Int_t)size == gMemSize) {
134 for (int i = 0; i < gTraceIndex; i++)
135 if (gTraceArray[i] == vp) {
136 gTraceArray[i] = nullptr;
137 break;
138 }
139 }
140 if (size >= kObjMaxSize)
141 gFreed[kObjMaxSize-1]++;
142 else
143 gFreed[size]++;
144 gFreedTotal += size;
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Allocate a block of memory, that later can be resized using
149/// TStorage::ReAlloc().
150
152{
153 static const char *where = "TStorage::Alloc";
154
155#ifndef WIN32
156 void *vp = ::operator new[](size);
157#else
158 void *vp = ::operator new(size);
159#endif
160 if (vp == nullptr)
161 Fatal(where, "%s", gSpaceErr);
162
163 return vp;
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// De-allocate block of memory, that was allocated via TStorage::Alloc().
168
169void TStorage::Dealloc(void *ptr)
170{
171#ifndef WIN32
172 ::operator delete[](ptr);
173#else
174 ::operator delete(ptr);
175#endif
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// Reallocate (i.e. resize) block of memory. Checks if current size is
180/// equal to oldsize. If not memory was overwritten.
181
182void *TStorage::ReAlloc(void *ovp, size_t size, size_t oldsize)
183{
184 // Needs to be protected by global mutex
185 {
187
189 return (*fgReAllocCHook)(ovp, size, oldsize);
190 }
191
192 static const char *where = "TStorage::ReAlloc";
193
194 if (oldsize == size)
195 return ovp;
196
197#ifndef WIN32
198 void *vp = ::operator new[](size);
199#else
200 void *vp = ::operator new(size);
201#endif
202 if (vp == nullptr) {
203 Fatal(where, "%s", gSpaceErr);
204 return nullptr; // Unreachable unless gErrorIgnoreLevel > kFatal.
205 }
206
207 if (ovp == nullptr)
208 return vp;
209
210 if (size > oldsize) {
211 memcpy(vp, ovp, oldsize);
212 memset((char*)vp+oldsize, 0, size-oldsize);
213 } else
214 memcpy(vp, ovp, size);
215#ifndef WIN32
216 ::operator delete[](ovp);
217#else
218 ::operator delete(ovp);
219#endif
220 return vp;
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Reallocate (i.e. resize) array of chars. Size and oldsize are
225/// in number of chars.
226
227char *TStorage::ReAllocChar(char *ovp, size_t size, size_t oldsize)
228{
229 static const char *where = "TStorage::ReAllocChar";
230
231 char *vp;
232 if (ovp == nullptr) {
233 vp = new char[size];
234 if (vp == nullptr)
235 Fatal(where, "%s", gSpaceErr);
236 return vp;
237 }
238 if (oldsize == size)
239 return ovp;
240
241 vp = new char[size];
242 if (vp == nullptr)
243 Fatal(where, "%s", gSpaceErr);
244 if (size > oldsize) {
245 memcpy(vp, ovp, oldsize);
246 memset((char*)vp+oldsize, 0, size-oldsize);
247 } else
248 memcpy(vp, ovp, size);
249 delete [] ovp;
250 return vp;
251}
252
253////////////////////////////////////////////////////////////////////////////////
254/// Reallocate (i.e. resize) array of integers. Size and oldsize are
255/// number of integers (not number of bytes).
256
257Int_t *TStorage::ReAllocInt(Int_t *ovp, size_t size, size_t oldsize)
258{
259 static const char *where = "TStorage::ReAllocInt";
260
261 Int_t *vp;
262 if (ovp == nullptr) {
263 vp = new Int_t[size];
264 if (vp == nullptr)
265 Fatal(where, "%s", gSpaceErr);
266 return vp;
267 }
268 if (oldsize == size)
269 return ovp;
270
271 vp = new Int_t[size];
272 if (vp == nullptr)
273 Fatal(where, "%s", gSpaceErr);
274 if (size > oldsize) {
275 memcpy(vp, ovp, oldsize*sizeof(Int_t));
276 memset((Int_t*)vp+oldsize, 0, (size-oldsize)*sizeof(Int_t));
277 } else
278 memcpy(vp, ovp, size*sizeof(Int_t));
279 delete [] ovp;
280 return vp;
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// Used to allocate a TObject on the heap (via TObject::operator new()).
285/// Directly after this routine one can call (in the TObject ctor)
286/// TStorage::FilledByObjectAlloc() to find out if the just created object is on
287/// the heap. This technique is necessary as there is one stack per thread
288/// and we can not rely on comparison with the current stack memory position.
289
290void *TStorage::ObjectAlloc(size_t sz)
291{
292 void* space = ::operator new(sz);
293 memset(space, kObjectAllocMemValue, sz);
294 return space;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Used to allocate array of TObject on the heap (via TObject::operator new[]()).
299/// Unlike the 'singular' ObjectAlloc, we do not mark those object has being
300/// allocated on the heap as they can not be individually deleted.
301
303{
304 void* space = ::operator new(sz);
305 return space;
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Used to allocate a TObject on the heap (via TObject::operator new(size_t,void*))
310/// in position vp. vp is already allocated (maybe on heap, maybe on
311/// stack) so just return.
312
313void *TStorage::ObjectAlloc(size_t , void *vp)
314{
315 return vp;
316}
317
318////////////////////////////////////////////////////////////////////////////////
319/// Used to deallocate a TObject on the heap (via TObject::operator delete()).
320
322{
323
324 ::operator delete(vp);
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// Used to deallocate a TObject on the heap (via TObject::operator delete(void*,void*)).
329
330void TStorage::ObjectDealloc(void *vp, void *ptr)
331{
332 if (vp && ptr) { }
333}
334
335#ifdef R__SIZEDDELETE
336////////////////////////////////////////////////////////////////////////////////
337/// Used to deallocate a TObject on the heap (via TObject::operator delete()),
338/// for sized deallocation.
339
340void TStorage::ObjectDealloc(void *vp, size_t size)
341{
342 ::operator delete(vp, size);
343}
344#endif
345
346////////////////////////////////////////////////////////////////////////////////
347/// Set a free handler.
348
350{
351 fgFreeHook = fh;
353}
354
355////////////////////////////////////////////////////////////////////////////////
356/// Set a custom ReAlloc handlers. This function is typically
357/// called via a static object in the ROOT libNew.so shared library.
358
360{
361 fgReAllocCHook = rh2;
362}
363
364////////////////////////////////////////////////////////////////////////////////
365/// Print memory usage statistics.
366
368{
369 // Needs to be protected by global mutex
371
372#if defined(MEM_DEBUG) && defined(MEM_STAT)
373
375 return;
376
377 //Printf("");
378 Printf("Heap statistics");
379 Printf("%12s%12s%12s%12s", "size", "alloc", "free", "diff");
380 Printf("================================================");
381
382 int i;
383 for (i = 0; i < (int)kObjMaxSize; i++)
384 if (gAllocated[i] != gFreed[i])
385 //if (gAllocated[i])
386 Printf("%12d%12d%12d%12d", i, gAllocated[i], gFreed[i],
387 gAllocated[i]-gFreed[i]);
388
390 Printf("------------------------------------------------");
391 Printf("Total: %12d%12d%12d", gAllocatedTotal, gFreedTotal,
393 }
394
395 if (gMemSize != -1) {
396 Printf("------------------------------------------------");
397 for (i= 0; i < gTraceIndex; i++)
398 if (gTraceArray[i])
399 Printf("block %d of size %d not freed", i, gMemSize);
400 }
401 Printf("================================================");
402 Printf(" ");
403#endif
404}
405
406////////////////////////////////////////////////////////////////////////////////
407/// Enable memory usage statistics gathering. Size is the size of the memory
408/// block that should be trapped and ix is after how many such allocations
409/// the trap should happen.
410
412{
413#ifdef MEM_STAT
414 gMemSize = size;
415 gMemIndex = ix;
417#else
418 int idum = size; int iidum = ix;
419#endif
420}
421
422////////////////////////////////////////////////////////////////////////////////
423///return static free hook data
424
426{
427 return fgFreeHookData;
428}
429
430////////////////////////////////////////////////////////////////////////////////
431///return the has custom delete flag
432
434{
436}
437
438////////////////////////////////////////////////////////////////////////////////
439///set the has custom delete flag
440
442{
444}
445
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
#define ClassImp(name)
Definition Rtypes.h:377
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:244
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:84
static const char * gSpaceErr
Definition TStorage.cxx:75
static Int_t gTraceCapacity
Definition TStorage.cxx:83
static Int_t gTraceIndex
Definition TStorage.cxx:83
static Bool_t gMemStatistics
Definition TStorage.cxx:79
static Int_t gMemSize
Definition TStorage.cxx:84
const size_t kObjMaxSize
Definition TStorage.cxx:77
static Int_t gFreed[kObjMaxSize]
Definition TStorage.cxx:80
static void ** gTraceArray
Definition TStorage.cxx:82
static Int_t gAllocated[kObjMaxSize]
Definition TStorage.cxx:80
static Int_t gAllocatedTotal
Definition TStorage.cxx:81
#define storage_size(p)
Definition TStorage.cxx:56
static Int_t gFreedTotal
Definition TStorage.cxx:81
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:39
static void RemoveStat(void *p)
Register a memory free operation.
Definition TStorage.cxx:128
static void * Alloc(size_t size)
Allocate a block of memory, that later can be resized using TStorage::ReAlloc().
Definition TStorage.cxx:151
static Bool_t fgHasCustomNewDelete
Definition TStorage.h:40
static char * ReAllocChar(char *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition TStorage.cxx:227
static FreeHookFun_t fgFreeHook
Definition TStorage.h:37
static Bool_t HasCustomNewDelete()
return the has custom delete flag
Definition TStorage.cxx:433
static void EnterStat(size_t size, void *p)
Register a memory allocation operation.
Definition TStorage.cxx:98
static void ObjectDealloc(void *vp)
Used to deallocate a TObject on the heap (via TObject::operator delete()).
Definition TStorage.cxx:321
static void SetFreeHook(FreeHookFun_t func, void *data)
Set a free handler.
Definition TStorage.cxx:349
static void SetCustomNewDelete()
set the has custom delete flag
Definition TStorage.cxx:441
static void * GetFreeHookData()
return static free hook data
Definition TStorage.cxx:425
static void SetMaxBlockSize(size_t size)
Definition TStorage.h:133
static void * fgFreeHookData
Definition TStorage.h:38
static const UInt_t kObjectAllocMemValue
Definition TStorage.h:48
static void Dealloc(void *ptr)
De-allocate block of memory, that was allocated via TStorage::Alloc().
Definition TStorage.cxx:169
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:257
static void SetReAllocHooks(ReAllocFun_t func1, ReAllocCFun_t func2)
Set a custom ReAlloc handlers.
Definition TStorage.cxx:359
static void * ObjectAllocArray(size_t size)
Used to allocate array of TObject on the heap (via TObject::operator new[]()).
Definition TStorage.cxx:302
static void EnableStatistics(int size=-1, int ix=-1)
Enable memory usage statistics gathering.
Definition TStorage.cxx:411
static size_t GetMaxBlockSize()
Definition TStorage.h:131
static void * ReAlloc(void *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition TStorage.cxx:182
static void * ObjectAlloc(size_t size)
Used to allocate a TObject on the heap (via TObject::operator new()).
Definition TStorage.cxx:290
static void PrintStatistics()
Print memory usage statistics.
Definition TStorage.cxx:367
R__EXTERN FreeIfTMapFile_t * gFreeIfTMapFile
Definition TStorage.h:140
R__EXTERN void * gMmallocDesc
Definition TStorage.h:141
bool(void *) FreeIfTMapFile_t
Definition TStorage.h:139
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250