MemCheck.h

Go to the documentation of this file.
00001 // @(#)root/new:$Id: MemCheck.h 20882 2007-11-19 11:31:26Z rdm $
00002 // Author: D.Bertini and M.Ivanov   10/08/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //****************************************************************************//
00013 //
00014 //
00015 // MemCheck is used to check the memory in ROOT based applications.
00016 //
00017 // Principe:
00018 //  A memory leak often arises whenever memory allocated through
00019 //  (new, new[]) is never returned via a corresponding (delete, delete[]).
00020 //  Redefining a special version of (operator new, operator delete) will
00021 //  allow the bookkeeping of created pointers to chunks of memory and, at
00022 //  the same time, pointers to the current function (and all of its callers
00023 //  scanning the stack) in order to trace back where the memory is not freed.
00024 //  This specific bookkeeping of pointers will be done by a kind of
00025 //  "memory info" container class TMemHashTable that will be used via
00026 //  the ROOT memory management defined inside the NewDelete.cxx file.
00027 //
00028 //  To activate the memory checker you have to set in the .rootrc file
00029 //  the resource Root.MemCheck to 1 (e.g.: Root.MemCheck: 1) and you
00030 //  have to link with libNew.so (e.g. use root-config --new --libs) or
00031 //  use rootn.exe. When all this is the case you will find at the end
00032 //  of the program execution a file "memcheck.out" in the directory
00033 //  where you started your ROOT program. Alternatively you can set
00034 //  the resource Root.MemCheckFile to the name of a file to which
00035 //  the leak information will be written. The contents of this
00036 //  "memcheck.out" file can be analyzed and transformed into printable
00037 //  text via the memprobe program (in $ROOTSYS/bin).
00038 //
00039 // (c) 2000 : Gesellschaft fuer Schwerionenforschung GmbH
00040 //            Planckstrasse, 1
00041 //            D-64291 Darmstadt
00042 //            Germany
00043 //
00044 // Created 10/08/2000 by: D.Bertini and M.Ivanov.
00045 // Based on ideas from LeakTracer by Erwin Andreasen.
00046 //
00047 // - Updated:
00048 //    Date: 12/02/2001 Adapt script to new GDB 5.0, new glibc2.2.x and gcc 2.96.
00049 //    Date: 23/10/2000 (hash mechanism speeding up the bookkeeping)
00050 //
00051 // - Documentation:
00052 //
00053 //    http://www-hades.gsi.de/~dbertini/mem.html
00054 //
00055 //****************************************************************************//
00056 
00057 #include "TROOT.h"
00058 
00059 
00060 class TStackInfo {
00061 public:
00062    UInt_t      fSize;             //size of the stack
00063    Int_t       fTotalAllocCount;  //total number of allocation for stack sequence
00064    Int_t       fTotalAllocSize;   //total size of allocated memory
00065    Int_t       fAllocCount;       //current number of allocation-deallocation
00066    Int_t       fAllocSize;        //current allocated size
00067    TStackInfo *fNextHash;         //index-pointer to the next info for given hash value
00068 
00069 public:
00070    void     Init(Int_t stacksize, void **stackptrs); //initialization
00071    void     Inc(Int_t memSize);  //increment counters -when memory allocated
00072    void     Dec(Int_t memSize);  //decrement counters -when memory deallocated
00073    ULong_t  Hash();
00074    Int_t    IsEqual(UInt_t size, void **ptr);
00075    void    *StackAt(UInt_t i);
00076    TStackInfo *Next();    //index of the next entries
00077 
00078    static ULong_t HashStack(UInt_t size, void **ptr);
00079 };
00080 
00081 
00082 class TStackTable {
00083 private:
00084    char         *fTable;      //pointer to the table
00085    TStackInfo  **fHashTable;  //pointer to the hash table
00086    Int_t         fSize;       //current size of the table
00087    Int_t         fHashSize;   //current size of the hash table
00088    Int_t         fCount;      //number of entries in table
00089    char         *fNext;       //pointer to the last stack info
00090 
00091    void Expand(Int_t newsize);
00092 
00093 public:
00094    void        Init();
00095    TStackInfo *AddInfo(Int_t size, void **stackptrs);
00096    TStackInfo *FindInfo(Int_t size, void **stackptrs);
00097    Int_t       GetIndex(TStackInfo *info);
00098    TStackInfo *GetInfo(Int_t index);
00099    TStackInfo *First() { return (TStackInfo *)fTable; }
00100 };
00101 
00102 
00103 class TMemInfo {
00104 public:
00105    void   *fAddress;    //mem address
00106    size_t  fSize;       //size of the allocated memory
00107    Int_t   fStackIndex; //index of the stack info
00108 };
00109 
00110 class TMemTable {
00111 public:
00112    Int_t     fAllocCount;    //number of memory allocation blocks
00113    Int_t     fMemSize;       //total memory allocated size
00114    Int_t     fTableSize;     //amount of entries in the below array
00115    Int_t     fFirstFreeSpot; //where is the first free spot in the leaks array?
00116    TMemInfo *fLeaks;         //leak table
00117 };
00118 
00119 class TDeleteTable {
00120 public:
00121    Int_t     fAllocCount;    //how many memory blocks do we have
00122    Int_t     fTableSize;     //amount of entries in the below array
00123    TMemInfo *fLeaks;         //leak table
00124 };
00125 
00126 
00127 class TMemHashTable {
00128 public:
00129    static Int_t        fgSize;            //size of hash table
00130    static TMemTable  **fgLeak;            //pointer to the hash table
00131    static Int_t        fgAllocCount;      //number of memory allocation blocks
00132    static TStackTable  fgStackTable;      //table with stack pointers
00133    static TDeleteTable fgMultDeleteTable; //pointer to the table
00134 
00135    ~TMemHashTable() { if (TROOT::MemCheck()) Dump(); }
00136 
00137    static void  Init();
00138    static void  RehashLeak(Int_t newSize);             //rehash leak pointers
00139    static void *AddPointer(size_t size, void *ptr=0);  //add pointer to the table
00140    static void  FreePointer(void *p);                  //free pointer
00141    static void  Dump();                                //write leaks to the output file
00142 };
00143 
00144 
00145 
00146 inline void TStackInfo::Inc(Int_t memSize)
00147 {
00148    fTotalAllocCount += 1;
00149    fTotalAllocSize  += memSize;
00150    fAllocCount      += 1;
00151    fAllocSize       += memSize;
00152 }
00153 
00154 inline void TStackInfo::Dec(int memSize)
00155 {
00156    fAllocCount -= 1;
00157    fAllocSize  -= memSize;
00158 }
00159 
00160 inline ULong_t TStackInfo::Hash()
00161 {
00162    return HashStack(fSize, (void**)&(this[1]));
00163 }
00164 
00165 inline void *TStackInfo::StackAt(UInt_t i)
00166 {
00167    //return i<fSize ? ((char*)&(this[1]))+i*sizeof(void*):0;
00168    void **stptr = (void**)&(this[1]);
00169    return i < fSize ? stptr[i] : 0;
00170 }
00171 
00172 inline TStackInfo *TStackInfo::Next()
00173 {
00174    //return (TStackInfo*)((char*)(&this[1])+fSize*sizeof(void*));
00175    return (TStackInfo*)((char*)(this)+fSize*sizeof(void*)+sizeof(TStackInfo));
00176 }

Generated on Tue Jul 5 14:11:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1