https://github.com/root-project/root
Tip revision: 6b8f54808eb13103e87cae19c642aec474270422 authored by Axel Naumann on 11 September 2019, 13:36:49 UTC
Update ROOT version files to v6.18/04.
Update ROOT version files to v6.18/04.
Tip revision: 6b8f548
MemCheck.h
// @(#)root/new:$Id$
// Author: D.Bertini and M.Ivanov 10/08/2000
/*************************************************************************
* Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//****************************************************************************//
//
//
// MemCheck is used to check the memory in ROOT based applications.
//
// Principe:
// A memory leak often arises whenever memory allocated through
// (new, new[]) is never returned via a corresponding (delete, delete[]).
// Redefining a special version of (operator new, operator delete) will
// allow the bookkeeping of created pointers to chunks of memory and, at
// the same time, pointers to the current function (and all of its callers
// scanning the stack) in order to trace back where the memory is not freed.
// This specific bookkeeping of pointers will be done by a kind of
// "memory info" container class TMemHashTable that will be used via
// the ROOT memory management defined inside the NewDelete.cxx file.
//
// To activate the memory checker you have to set in the .rootrc file
// the resource Root.MemCheck to 1 (e.g.: Root.MemCheck: 1) and you
// have to link with libNew.so (e.g. use root-config --new --libs) or
// use rootn.exe. When all this is the case you will find at the end
// of the program execution a file "memcheck.out" in the directory
// where you started your ROOT program. Alternatively you can set
// the resource Root.MemCheckFile to the name of a file to which
// the leak information will be written. The contents of this
// "memcheck.out" file can be analyzed and transformed into printable
// text via the memprobe program (in $ROOTSYS/bin).
//
// (c) 2000 : Gesellschaft fuer Schwerionenforschung GmbH
// Planckstrasse, 1
// D-64291 Darmstadt
// Germany
//
// Created 10/08/2000 by: D.Bertini and M.Ivanov.
// Based on ideas from LeakTracer by Erwin Andreasen.
//
// - Updated:
// Date: 12/02/2001 Adapt script to new GDB 5.0, new glibc2.2.x and gcc 2.96.
// Date: 23/10/2000 (hash mechanism speeding up the bookkeeping)
//
// - Documentation:
//
// http://www-hades.gsi.de/~dbertini/mem.html
//
//****************************************************************************//
#include "TROOT.h"
class TStackInfo {
public:
UInt_t fSize; //size of the stack
Int_t fTotalAllocCount; //total number of allocation for stack sequence
Int_t fTotalAllocSize; //total size of allocated memory
Int_t fAllocCount; //current number of allocation-deallocation
Int_t fAllocSize; //current allocated size
TStackInfo *fNextHash; //index-pointer to the next info for given hash value
public:
void Init(Int_t stacksize, void **stackptrs); //initialization
void Inc(Int_t memSize); //increment counters -when memory allocated
void Dec(Int_t memSize); //decrement counters -when memory deallocated
ULong_t Hash();
Int_t IsEqual(UInt_t size, void **ptr);
void *StackAt(UInt_t i);
TStackInfo *Next(); //index of the next entries
static ULong_t HashStack(UInt_t size, void **ptr);
};
class TStackTable {
private:
char *fTable; //pointer to the table
TStackInfo **fHashTable; //pointer to the hash table
Int_t fSize; //current size of the table
Int_t fHashSize; //current size of the hash table
Int_t fCount; //number of entries in table
char *fNext; //pointer to the last stack info
void Expand(Int_t newsize);
public:
void Init();
TStackInfo *AddInfo(Int_t size, void **stackptrs);
TStackInfo *FindInfo(Int_t size, void **stackptrs);
Int_t GetIndex(TStackInfo *info);
TStackInfo *GetInfo(Int_t index);
TStackInfo *First() { return (TStackInfo *)fTable; }
};
class TMemInfo {
public:
void *fAddress; //mem address
size_t fSize; //size of the allocated memory
Int_t fStackIndex; //index of the stack info
};
class TMemTable {
public:
Int_t fAllocCount; //number of memory allocation blocks
Int_t fMemSize; //total memory allocated size
Int_t fTableSize; //amount of entries in the below array
Int_t fFirstFreeSpot; //where is the first free spot in the leaks array?
TMemInfo *fLeaks; //leak table
};
class TDeleteTable {
public:
Int_t fAllocCount; //how many memory blocks do we have
Int_t fTableSize; //amount of entries in the below array
TMemInfo *fLeaks; //leak table
};
class TMemHashTable {
public:
static Int_t fgSize; //size of hash table
static TMemTable **fgLeak; //pointer to the hash table
static Int_t fgAllocCount; //number of memory allocation blocks
static TStackTable fgStackTable; //table with stack pointers
static TDeleteTable fgMultDeleteTable; //pointer to the table
~TMemHashTable() { if (TROOT::MemCheck()) Dump(); }
static void Init();
static void RehashLeak(Int_t newSize); //rehash leak pointers
static void *AddPointer(size_t size, void *ptr=0); //add pointer to the table
static void FreePointer(void *p); //free pointer
static void Dump(); //write leaks to the output file
};
inline void TStackInfo::Inc(Int_t memSize)
{
fTotalAllocCount += 1;
fTotalAllocSize += memSize;
fAllocCount += 1;
fAllocSize += memSize;
}
inline void TStackInfo::Dec(int memSize)
{
fAllocCount -= 1;
fAllocSize -= memSize;
}
inline ULong_t TStackInfo::Hash()
{
return HashStack(fSize, (void**)&(this[1]));
}
inline void *TStackInfo::StackAt(UInt_t i)
{
//return i<fSize ? ((char*)&(this[1]))+i*sizeof(void*):0;
void **stptr = (void**)&(this[1]);
return i < fSize ? stptr[i] : 0;
}
inline TStackInfo *TStackInfo::Next()
{
//return (TStackInfo*)((char*)(&this[1])+fSize*sizeof(void*));
return (TStackInfo*)((char*)(this)+fSize*sizeof(void*)+sizeof(TStackInfo));
}