[ROOT] Mem leak using TTree with TObjArray+TclonesArray

From: Luigi Del Buono (delbuono@in2p3.fr)
Date: Wed Oct 03 2001 - 12:07:35 MEST


Hi rooters,

I waited a long time before posting this, but I have no clue on this
problem so...

I seem to have a memory leak that i cannot trace to my personal code...I
have made a much simplified version of code which apparently reproduces
the problem.
The leak is eating something like 10 Kbytes of memory for each "iteration"
in the main loop of this code, it's bigger in the full code version.
This prevents me from running on big amounts of data (which is needed, of
course).

The problem happens when reading a ROOT TTree file which contains
occurences of one simple structure with one TObjArray* member, the
TObjArray elements themselves containing another object which itself has a
TClonesArray* member.
So, this is a story about storing and reading in a Root TTree a TObjArray
which elements are mainly TClonesArray. The problem appears while READING
the TTree.

Another problem is that, after a few thousand events, the program is
printing out thousands of Warning messages like:

Warning in <TObjectTable::Remove>: 0x0a61b7b4 not found at 1739
Warning in <TObjectTable::Remove>: 0x0a61d8fc not found at 1739
Warning in <TObjectTable::Remove>: 0x0a61d8f0 not found at 1739 
...
Warning in <TObjectTable::Remove>: 0x0a7a3a5c not found at 5779
Warning in <TObjectTable::Remove>: 0x0a7a3a50 not found at 5779
Warning in <TObjectTable::Remove>: 0x0a7a3a98 not found at 5779
Warning in <TObjectTable::Remove>: 0x0a7a3a18 not found at 5779

I have no idea of what is happening, so i am calling the experts...

Configuration info: Linux RedHat 6.2, Root 3.01/06, the program is
compiled whith gcc egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)

I'll try to give here the main elements of the code, so people can see if
something is wrong somewhere.

Thanks any help/suggestion


//
//------Base class stored in tree--------------------------
//
class TauEvent : public TObject {
    
public:
    //Constructor
    TauEvent();
    
    //Destructor
    ~TauEvent();
    
    //Accessors
    TauC1 &GetC1(Int_t iC1);  //returns a pointer to a 3-1 comb. array
        
public:    
    TObjArray *C1;    //The TObjArray
      
public:
    ClassDef(TauEvent,1)	
};      


//
//-----Class to be stored in the TObjArray--------------------
//
class TauC1 : public TObject {
    
public:
    //Constructor
    TauC1();
    
    //Destructor
    ~TauC1();

    //Access sub data
    TauC2 *AddC2(Int_t iC2);   
    TauC2 &GetC2(Int_t iC2); 
    TClonesArray &GetC2() { return *C2;};
    
    //3-body info
    TLorentzVector V1;   
    
private:
    TClonesArray *C2;    //the TClonesArray
    
public:
    ClassDef(TauC1,1)	
};      


//
//--------Constructor and destructor of TauEvent
//
//contructor
ClassImp(TauEvent)

TauEvent::TauEvent() : 
C1(0)
{
  C1=new TObjArray();
}

//destructor
TauEvent::~TauEvent() 
{  
  if (C1) {
    if(C1->GetEntries()>0) C1->Delete();
    delete C1;
  }
}


//
//--------Constructor and destructor of TauC1
//
//contructor
ClassImp(TauC1)

TauC1::TauC1()
{
  C2=new TClonesArray("TauC2");
}

//destructor
TauC1::~TauC1() 
{
  if(C2) {
    if(C2->GetEntries()>0) C2->Delete();
    delete C2;
  }
}

//
//------Data fill & access routines
//
TauC2 *TauC1::AddC2(Int_t iC2) {
  return (new ((*C2)[iC2]) TauC2);
}


//
//TTree creation code
//
Rfile=new TFile("Event.root","RECREATE","EventInfo",1);   //0=no compress
Rtree=new TTree("EventTree","EventInfo tree",0);
Rtree->SetBranchStyle(0);   //!!!!old style branch (ROOT 3.01/06)
Rtree->Branch("C1", "TObjArray", &(EventInfo.C1), 2048, 0);  


//
//Writing loop code (called for each "event")
//
for (int itau1=0;itau1<1;itau1++) { //structure 1 loop
  TauC1 *C1=new TauC1;
  C1->V1.SetXYZT(1,2,3,4);   

  for (int itau2=0;itau2<1;itau2++) {  //structure 2 loop
    TauC2 *C2=C1->AddC2(itau2);
    C2->V2.SetXYZT(10,20,30,40);
  }

  EventInfo.C1->Add(C1);  //Fill C1 structure level
}
Rtree->Fill();   //final fill for root data
EventInfo.C1->Delete();   //clear local objects in event Tree


//
// Reading loop code
//
TChain *Tree;   //create global tree
TBranch *C1Branch;
TauEvent EvI;
Int_t NEventMax;
TObjectTable* gObjectTable;

//Load tree
Int_t init_tree()
{
  //Multi file access
  Tree=new TChain("EventTree");    
  Tree->Add("Event.root/EventTree");     //Connect root file 

  //Connect root branches to local variables  ("EvI")
  C1Branch=Tree->GetBranch("C1");
  C1Branch->SetAddress(&(EvI.C1));   
  C1Branch->SetAutoDelete(kTRUE);  //

  Int_t Nevent=(Int_t)Tree->GetEntries();
  cout << "Main: Number of events in tree: " << Nevent << endl;
   
  return 0;
}

//reading loop
Int_t plot_t31()
{   
  TH1F hV1X("hV1X", "V1 x", 60, 0., 5.); 
  Int_t Nevent=(Int_t)Tree->GetEntries();
  
  for(int iev=0;iev<TMath::Min(Nevent,NEventMax);iev++) {    //fill histos
    Tree->GetEntry(iev);
    if(iev%100==0) cout << "iev: " << iev << endl;

//    gObjectTable->Print();
    
    for(int iC1=0;iC1<EvI.C1->GetEntries();iC1++) {
      TauC1 &C1=EvI.GetC1(iC1);
      Double_t V1X=C1.V1.X();
      hV1X.Fill(V1X);
      cout << "V1X:" << V1X << endl;
    }
    if(EvI.C1->GetEntries()>0) EvI.C1->Delete();   //clear local objects
in event
  }
    
  TCanvas *c1 = new TCanvas("c1","Test",200,10,900,1000);
  c1->Clear();
  c1->Divide(1,2);
  c1->cd(1); hV1X.DrawCopy();

  return 0;  
}



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:51:02 MET