[ROOT] Memory leak in TFile?

From: Chitov Iouri (chitov@lal.in2p3.fr)
Date: Sun Apr 14 2002 - 17:27:46 MEST


Dear rooters,

In my program I create TFile from a set of raw binary data files.
Repeating this procedure several times and comparing the
gObjectTable->Print() outputs I see these results:

Differences in the table of objects:
31c31
< TBasket                         2          2      112           224
224
---
> TBasket                         3          3      112           336
336
77c77
< TBuffer                         2          2       56           112
112
---
> TBuffer                         3          3       56           168
168

Differences in the table of objects:
31c31
< TBasket                         3          3      112           336
336
---
> TBasket                         4          4      112           448
448
77c77
< TBuffer                         3          3       56           168
168
---
> TBuffer                         4          4       56           224
224

Ideas? It seems, like  whether I close TFile in the wrong way, or
TFile desctructor forgot to clear something :).

Open TFile procedure:

fEvent = new TgvEvent();
fRun = new TgvRun();
fFile = new TFile(fn,"RECREATE");
fTEvent = new TTree("ev","TGV Events");
fTgvRun  = new TTree("rh","TGV Run Header");
fTEvent->Branch("Event","TgvEvent",&fEvent,32000,99);
fTgvRun->Branch("RunHeader","TgvRun",&fRun,1000,99);

Close procedure:

fFile->Write();
delete fFile;
fFile = 0;

And Event class files are in attachment.

Best wishes,
Yuriy.



// TGV SOFTWARE LIBRARY
// Author: Shitov Yuriy <mailto:yuriy@nu.jinr.ru>
// Copyright: 2002 (C) JINR, Dubna, Russia

//         CLASSES TO STORE TGV DATA IN THE ROOT FORMAT 

#ifndef _TGVEVENT_H
#define _TGVEVENT_H

#include "tgv.h"

//________________________________________________________
//
// TgvDStat - Class to save detector status during each TGV run
//

class TgvDStat: public TObject { // Status of detectors during one run
 protected:
  UShort_t fNDet;        // Detector number (1-32)
  UShort_t fThADC;       // ADC Threshold
 public:
  TgvDStat() {}
  TgvDStat(UShort_t det,UShort_t thADC){fNDet=det;fThADC=thADC;}
  virtual ~TgvDStat() {}
  UShort_t  Det() const { return fNDet;}
  UShort_t  ThADC() const { return fThADC;}

  ClassDef(TgvDStat,1) // Save detector status during each TGV run
};

//________________________________________________________
//
// TgvRun - Class to save information about each TGV Run
//

class TgvRun: public TObject {
 protected:
  UInt_t        fRunNumber; // Run number
  UInt_t        fTimeSec;   // Time of Run start (first event) (seconds from Epoche)
  UInt_t        fTimeUSec;  // microseconds of Run start
  UShort_t      fNDStat;    // number of status detector records
  TClonesArray *fDStats;    //-> array of detector status records

  static TClonesArray *fgDStats;

 public:
  TgvRun();
  virtual ~TgvRun();
  Char_t       *Set(Char_t*, UInt_t rn);      // fill runheader
  UInt_t        Time()  {return fTimeSec;}    // get run time (sec from Epoche)
  UInt_t        UTime() {return fTimeUSec;}   // get microseconds of run 
  UInt_t        Run()   {return fRunNumber;}  // get Run number
  UShort_t      ThADC(UShort_t det);          // get ADC threshold
  void          Clear(Option_t *option ="");  // Clear variables
  static void   Reset(Option_t *option ="");  // Reset variables
  void          Print();                      // Print run header

  ClassDef(TgvRun,1)  // Save information about each TGV Run
};

//________________________________________________________
//
// TgvDHit - Class to save one Detector Hit of TGV event (one event may
// have up to DET_NUM  hits (see tgv.h)

class TgvDHit: public TObject {
 protected:
  UShort_t fNDet;   // Detector number (1-32)
  UShort_t fADC;    // ADC
  UShort_t fQDC;    // QDC
  UShort_t fTDC;    // TDC
 public:
  TgvDHit() {}
  virtual ~TgvDHit() { }
  Char_t*   Set(Char_t*);
  UShort_t  Det() const { return fNDet;}
  UShort_t  ADC() const { return fADC;}
  UShort_t  QDC() const { return fQDC;}
  UShort_t  TDC() const { return fTDC;}

  ClassDef(TgvDHit,1) // Record for one detector hit of TGV event
};

//________________________________________________________
//
// TgvEvent - the basic TGV class to store one Event. One TGV Event
// can contain several detector hits (see TgvDHit)
//

class TgvEvent: public TObject { 
 protected:
  UInt_t        fRunEntry;  // Number of entry in the tree for RunHeader
  UInt_t        fSec;       // Absolute time of Event (seconds)
  UInt_t        fUSec;      // microseconds of absolute time
  Bool_t        fNitrogen;  // flag of Nitrogen filling
  UShort_t      fNDHit;    // number of detector hits
  TClonesArray *fDHits;    //-> array of detector hits  

  static TClonesArray *fgDHits;

 public:
  TgvEvent();
  virtual ~TgvEvent();
  void          Clear(Option_t *option ="");
  static void   Reset(Option_t *option ="");
  Char_t       *Set(Char_t*, UInt_t ent, UInt_t sec, UInt_t usec);
  UShort_t      Time()     const { return fSec; }
  UShort_t      UTime()    const { return fUSec; }
  Bool_t        N2()       const { return fNitrogen; }
  UShort_t      Hits()     const { return fNDHit; }
  UInt_t        RunEntry() const { return fRunEntry;}
  UShort_t      Det(UShort_t hit) const { 
	 return (hit < fNDHit) ? ( (TgvDHit*) fDHits->At(hit))->Det() : 0; }
  UShort_t      ADC(UShort_t hit) const { 
	 return (hit < fNDHit) ? ( (TgvDHit*) fDHits->At(hit))->ADC() : 0; }
  UShort_t      QDC(UShort_t hit) const { 
	 return (hit < fNDHit) ? ( (TgvDHit*) fDHits->At(hit))->QDC() : 0; }
  UShort_t      TDC(UShort_t hit) const { 
	 return (hit < fNDHit) ? ( (TgvDHit*) fDHits->At(hit))->TDC() : 0; }
  
  Char_t       *AddTgvDHit(UShort_t i, Char_t*);
  void          Print();
  
  ClassDef(TgvEvent,1)  // Store one TGV event
};

#endif /* _TGVEVENT_H */


// TGV SOFTWARE LIBRARY
// Author: Shitov Yuriy <mailto:yuriy@nu.jinr.ru>
// Copyright: 2002 (C) JINR, Dubna, Russia
  
#include "TGVEvent.h"
  
//________________________________________________________________
// TgvRun, TgvEvent, TgvDHit and TgvDStat are classes 
// to store TGV data in the ROOT format.
//
// TgvRun - Class to store information about each TGV Run. The status of
//   separate detectors during run is in the array of TgvDStat records
//   raw data file is reserved to save information about run 
//   conditions: 
//
//              FORMAT OF TGV RAW DATA FILE:
//
//   | Time | Utime | ADC Threshold(1-32)|...    |...|...|...|...|...|
//    \\~~~~~~ Run Header (512 bytes) ~~~~~~~~~~~/ \\~~~ TGV Events~~~/ 
//
//   Time,Utime - seconds and microseconds of absolute time of 
//   run start (first run event), unsigned int 4 byte
//   ADC - 32 unsigned 2-byte integers 
//   The rest of place in run header is reserved for future usage
//
// TgvEvent - the basic class to store one TGV Event. One Event
//   can contain several detector hits stored separately
//   in array of TgvDHit classes. 
//   TgvEvent is filled from raw data binary file 
//	  
//       FORMAT OF TGV EVENT IN RAW DATA FILE:
//	  
//       | ts | nhits | Hit(1) | ... | Hit(n) |
//	  
//   ts - time shift (microseconds) from Run start, unsigned int, 4-byte
//   n - number of detectors fired (multiplicity of Event), 1-byte 
//   If Nitrogen was filled during run, upper bit is set ( 127 | nhits)
//   Hit(i) - data stored for i-th detector fired (see TgvDHit)
//
// TgvDHit - class to save one detector hit of TGV event. One event may
//   have up to DET_NUM  hits (see tgv.h, DET_NUM=32 for TGV-2 setup)
//   TgvEvent is filled from raw data binary file
//
//            FORMAT OF DETECTOR HIT IN RAW DATA FILE:
//
//            | Detector Number | ADC | QDC | TDC |
//   All variables are unsigned 2-byte integers
//
// TgvDStat - class to save status of separate detector during each 
//   TGV run. Currently it holds software ADC thresholds.
//________________________________________________________
ClassImp(TgvDHit)

Char_t* TgvDHit::Set(Char_t* cp) 
{
  // Fill one detector hit cp - pointer to the detector hit in buffer of
  // raw data file. Returns the pointer to next position in the raw buffer.
	 
  fNDet = (UShort_t) *cp++ + 1;  /* RAW DATA FORMAT 0..31 -> NORMAL 1..32*/
  UShort_t* ip = (UShort_t*) cp;
  fADC = *ip++;
  fQDC = *ip++;
  fTDC = *ip++;
  return (Char_t*) ip; 
}

//________________________________________________________
TClonesArray *TgvEvent::fgDHits = 0;
ClassImp(TgvEvent)

TgvEvent::TgvEvent() 
{
// TgvEvent - the base TGV class. Information about detector hited is saved in
// TClonesArray (fDHits) of TgvDHit classes.

  if (!fgDHits) fgDHits = new TClonesArray("TgvDHit",DET_NUM);
  fDHits = fgDHits;
  fNDHit = 0;
};

Char_t *TgvEvent::AddTgvDHit(UShort_t i, Char_t* cp) 
{
  // Add detector hit to TGV event

  TClonesArray &dhits = *fDHits;
  TgvDHit *dhit = new (dhits[i]) TgvDHit();
  return dhit->Set(cp);
};

void TgvEvent::Clear(Option_t *option) 
{
  // Clear array of detector hits 

  fDHits->Clear(option);
}

void TgvEvent::Reset(Option_t *option)
{
  // Static function to reset all static objects for this event

  delete fgDHits; 
  fgDHits = 0;
}

Char_t *TgvEvent::Set(Char_t* cp, UInt_t ent, UInt_t sec, UInt_t usec) 
{
  // Fill TGV event. cp - pointer to the raw event in buffer 
  // (see TgvRawData). Returns pointer to the next raw event in the buffer.
  // ent - number of Entry of RunHeader (see TgvRun), 
  // sec,usec - time of Run start (used to define absolute time of event)

  UInt_t* n = (UInt_t*) cp;

  fRunEntry = ent;
  UInt_t ts = *n++;                // time shift in microseconds...
  fSec  = sec + (usec+ts)/1000000;
  fUSec = (usec+ts)%1000000;
  cp=(Char_t*) n;         
  fNitrogen = *cp >> 7;   // nitrogen
  fNDHit = *cp++ & 0xef;  // number of detector hits
  for (UShort_t i=0; i < fNDHit; i++)
	 cp=AddTgvDHit(i,cp);
  return cp;
};

void TgvEvent::Print() {

  TgvDHit *hit = 0;
  const time_t* tm = (time_t*) &fSec;
  cout << "Event Time: "<< ctime(tm);
  cout << "Nitrogen: ";
  if (fNitrogen) cout   << "  YES   " << endl;
  else cout   << "   NO   " << endl;
  cout << "Detector  ADC  QDC  TDC" << endl;
  for (UShort_t i = 0; i < fNDHit; i++) {
	 hit = (TgvDHit*) fDHits->At(i);
	 cout << setw(6) << hit->Det() << "  "
			<< setw(5) << hit->ADC() 
			<< setw(5) << hit->QDC() 
			<< setw(5) << hit->TDC() << endl;
  }
};

TgvEvent::~TgvEvent() {
  Clear();
}

//________________________________________________________
ClassImp(TgvDStat)

//________________________________________________________
TClonesArray *TgvRun::fgDStats = 0;
ClassImp(TgvRun)

TgvRun::TgvRun() {
  if (!fgDStats) fgDStats = new TClonesArray("TgvDStat",DET_NUM);
  fDStats = fgDStats;
}

UShort_t TgvRun::ThADC(UShort_t det) 
{
  // returns ADC threshold of i-th detector or 0 if not set

  for (UShort_t i = 0; i < fNDStat; i++)
	 if ( ((TgvDStat*)fDStats->At(i))->Det() == det )
		return ((TgvDStat*)fDStats->At(i))->ThADC();
  return 0;
}

TgvRun::~TgvRun() {
  Clear();
}

void TgvRun::Clear(Option_t *option) {
  fDStats->Clear(option);
}

void TgvRun::Reset(Option_t *option) 
{
  // Static function to reset all static objects for this Run header

  delete fgDStats; 
  fgDStats = 0;
}

Char_t* TgvRun::Set(Char_t* cp, UInt_t rn) 
{
  // Fill Run Header information, cp - pointer to
  // the begin of buffer witht raw data. returns pointer
  // to the first data event

  fRunNumber = rn;

  UInt_t* l = (UInt_t*) cp;
  fTimeSec  = *l++;
  fTimeUSec = *l++;

  UShort_t thADC;
  TClonesArray &dstats = *fDStats;
  TgvDStat *dstat;
  fNDStat = 0;
  for (UShort_t i = 0; i < DET_NUM; i++)
	 if ((thADC=*l++))
		dstat = new (dstats[fNDStat++]) TgvDStat(i+1,thADC);
  return cp+RUN_HEADER_SIZE;
};

void TgvRun::Print() {
  TgvDStat *stat = 0;
  const time_t* tm = (time_t*) &fTimeSec;
  cout << "Run Start Time (first Event): " << ctime(tm);
  cout << "Detector ThADC" << endl;
  for (UShort_t i = 0; i < fNDStat; i++) {
	 stat = (TgvDStat*) fDStats->At(i);
	 cout << setw(6) << stat->Det() << "  "
			<< setw(5) << stat->ThADC() << endl;
  }
};



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:50:50 MET