Re: [ROOT] Reading and cleaning of TClonesArray

From: Rene Brun (Rene.Brun@cern.ch)
Date: Tue Nov 26 2002 - 22:03:19 MET


Hi Ruben,

The recommended procedure is like in your modified example below.
By calling TClonesArray::Clear("C") (note the option "C")
the Clear function will be called for each object in
the TClonesArray. In the Clear function you can delete all
dynamic objects allocated by the constructor.
In CVS, I have added a function TNamed::Clear that deletes
the dynamic structures of a TNamed.
Note that You can implement a function Clear in any object derived
from TObject. Doing this simplifies the cleanup procedure
and makes it far more efficient than forcing a call
to TClonesArray::Delete. If you are forced to use the Delete function,
you should not use a TClonesArray, but a TObjArray.

Rene


void trrd()
{
  printf("Reading back the tree\n");
  char name[100];
  TClonesArray* fVTVerts = new TClonesArray("TNamed",10);
  //
  TFile* flin = new TFile("trout.root");
  TTree *tree = (TTree*)flin->Get("tree");
  TBranch* trbr = tree->GetBranch("mybr");
  trbr->SetAddress(&fVTVerts);
  //
  int nev = tree->GetEntries();
  int iv,nv;
  for (int iev=0;iev<nev;iev++) {
    trbr->GetEntry(iev);
    nv = fVTVerts->GetEntriesFast();
    printf("\n\nRead Event %d %d Old Vertices Are\n",iev,nv);
    fVTVerts->Print();
    printf("\nNow will call TClonesArray::Delete() and Create new
Vertices\n");
    fVTVerts->Clear("C");
    // Reanalyze event, creating new vertices
    nv = gRandom->Integer(5)+1;
    for (iv=0;iv<nv;iv++) {
      sprintf(name,"New Vtx %d of Ev %d",iv,iev);
      TNamed* vp = new ((*fVTVerts)[iv]) TNamed(name,name);
    }
    printf("\nUpdated Event: New Vertices Are:\n");
    fVTVerts->Print();
    fVTVerts->Clear("C");
  }
  delete flin;
  delete fVTVerts;
}

On Tue, 26 Nov 2002, Ruben Shahoian wrote:

> Thank you Rene,
> I am using Delete() in many situations, so I would like to know all
> restrictions. Did I understand your recipe correctly:
> 1) if the TClonesArray is read from the Tree, the user must free himself
> the "dynamic" part of the objects in the TClonesArray and then call Clear()
> 2) in other situations one can use TClonesArray::Delete() ?
> 
> Regards,
> 	Ruben
> 
> On Tue, 26 Nov 2002, Rene Brun wrote:
> 
> > Hi Ruben,
> > 
> > When your TClonesArray contains dynamic structures (like TNamed),
> > you must delete these dynamic structures before clearing
> > the array at each entry. I give an example of what you can do
> > below, still preserving some of the advantages of a TClonesArray.
> > 
> > Rene Brun
> > 
> > //_________________________________________________________
> > void trrd()
> > {
> >   printf("Reading back the tree\n");
> >   char name[100];
> >   TClonesArray* fVTVerts = new TClonesArray("TNamed",10);
> >   //
> >   TFile* flin = new TFile("trout.root");
> >   TTree *tree = (TTree*)flin->Get("tree");
> >   TBranch* trbr = tree->GetBranch("mybr");
> >   trbr->SetAddress(&fVTVerts);
> >   //
> >   int nev = tree->GetEntries();
> >   int iv,nv;
> >   for (int iev=0;iev<nev;iev++) {
> >     trbr->GetEntry(iev);
> >     nv = fVTVerts->GetEntriesFast();
> >     printf("\n\nRead Event %d %d Old Vertices Are\n",iev,nv);
> >     fVTVerts->Print();
> >     printf("\nNow will call TClonesArray::Delete() and Create new
> > Vertices\n");
> >     for (iv=0;iv<nv;iv++)
> > ((TNamed*)fVTVerts->At(iv))->SetNameTitle("","");
> >     fVTVerts->Clear();
> >     // Reanalyze event, creating new vertices
> >     nv = gRandom->Integer(5)+1;
> >     for (iv=0;iv<nv;iv++) {
> >       sprintf(name,"New Vtx %d of Ev %d",iv,iev);
> >       TNamed* vp = new ((*fVTVerts)[iv]) TNamed(name,name);
> >     }
> >     printf("\nUpdated Event: New Vertices Are:\n");
> >     fVTVerts->Print();
> >     for (iv=0;iv<nv;iv++)
> > ((TNamed*)fVTVerts->At(iv))->SetNameTitle("","");
> >     fVTVerts->Clear();
> >   }
> >   delete flin;
> >   delete fVTVerts;
> > }
> > 
> > 
> > On Mon, 25 Nov 2002, Ruben Shahoyan wrote:
> > 
> > > Hello,
> > > I have encontered the following problem:
> > > I am reading from the tree an event, which among other branches has one
> > > with TClonesArray of the vertices (objects which allocate the memory).
> > > I need to reanalize the event, so I have to clean the loaded vertices and
> > > create new ones. But if I call TClonesArray::Delete() to clean this array,
> > > loading next event produces SegVol.
> > > 
> > > Below I show the simple macros demonstrating the problem. Does anybody 
> > > know the solution?
> > > 
> > > Thanks in advance,
> > > 	Ruben Shahoyan
> > > 
> > > 
> > > //_____________________ Sample Macro________________________
> > > void trwr(int nev);
> > > void trrd();
> > > 
> > > void trtest(int nev=20) 
> > > {
> > >   // Step 1: Create tree, with the branch of TClonesArray of the objects
> > >   // allocating memory
> > >   trwr(nev);
> > >   //
> > >   // Step 2: Read the tree, trying to "modify" the TClonesArray
> > >   trrd();
> > > }
> > > 
> > > //_________________________________________________________
> > > void trwr(int nev)
> > > {
> > >   printf("Generating the tree with %d events\n",nev);
> > >   char name[100];
> > >   Int_t bfsize=32000;
> > >   Int_t split=2;
> > >   TClonesArray* fVTVerts = new TClonesArray("TNamed",10);
> > >   fVTVerts->SetOwner();
> > >   //
> > >   TFile* flout = new TFile("trout.root","RECREATE");
> > >   TTree *tree = new TTree("tree","tree");
> > >   tree->Branch("mybr","TClonesArray",&fVTVerts,bfsize,split);
> > >   //
> > >   for (int iev=0;iev<nev;iev++) {
> > >     fVTVerts->Delete();
> > >     int nv = gRandom->Integer(10)+1;
> > >     for (int iv=0;iv<nv;iv++) {
> > >       sprintf(name,"Vtx %d of Ev %d",iv,iev);
> > >       TNamed* vp = new ((*fVTVerts)[iv]) TNamed(name,name);
> > >     }
> > >     tree->Fill();
> > >   }
> > >   tree->Write();
> > >   delete tree;
> > >   flout->Close();
> > >   delete flout;
> > >   delete fVTVerts;
> > > }
> > > 
> > > //_________________________________________________________
> > > void trrd()
> > > {
> > >   printf("Reading back the tree\n");
> > >   char name[100];
> > >   TClonesArray* fVTVerts = new TClonesArray("TNamed",10);
> > >   fVTVerts->SetOwner();
> > >   //
> > >   TFile* flin = new TFile("trout.root");
> > >   TTree *tree = (TTree*)flin->Get("tree");
> > >   TBranch* trbr = tree->GetBranch("mybr");
> > >   trbr->SetAddress(&fVTVerts);
> > >   //
> > >   int nev = tree->GetEntries();
> > >   for (int iev=0;iev<nev;iev++) {
> > >     trbr->GetEntry(iev);
> > >     printf("\n\nRead Event %d %d\n Old Vertices Are",iev,fVTVerts->GetLast()+1);
> > >     fVTVerts->Print();
> > >     printf("\nNow will call TClonesArray::Delete() and Create new Vertices\n");
> > >     //fVTVerts->Clear();  !! Works with Clear, but will lead to memory leak! 
> > >     fVTVerts->Delete();
> > >     // Reanalyze event, creating new vertices
> > >     int nv = gRandom->Integer(5)+1;
> > >     for (int iv=0;iv<nv;iv++) {
> > >       sprintf(name,"New Vtx %d of Ev %d",iv,iev);
> > >       TNamed* vp = new ((*fVTVerts)[iv]) TNamed(name,name);
> > >     }
> > >     printf("\nUpdated Event: New Vertices Are:\n");
> > >     fVTVerts->Print();
> > >     //
> > >   }
> > >   delete tree;
> > >   flin->Close();
> > >   delete flin;
> > >   delete fVTVerts;
> > > }
> > > 
> > > 
> > 
> > 
> 



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