Re: Bug in TClonesArray::Streamer

From: Rene Brun (Rene.Brun@cern.ch)
Date: Tue Aug 24 1999 - 19:02:09 MEST


Hi Andy,
The non-split mode is not implemented for TClonesArray simply because
this is totally against the idea of a TClonesArray. You should use a
TObjArray
if it is your intention to stream the array to one single branch buffer.
In this case, for each event, you will spend time in the new/delete
process.
I have added below two macros showing how to use a TObjarray and one
single
branch.
The advantage of the TClonesArray is more evident when reading from the
Tree.
You can read about the TClonesArray advantage in the class documentation
   http://root.cern.ch/root/html/TClonesArray.html
I also suggest you read the explanation about the container classes at:
   http://root.cern.ch/root/Collection1.html
   ftp://root.cern.ch/root/course2.ps.gz

In your example, I assume that you are creating a second branch not
connected with the TClonesArray. I agree that the Root code should be
protected in case of a non-intended use of the class
(TLeafObject::ReadBasket
and TClonesArray::Streamer). I will add the protection.

Here are the two small macros showing how to use the TObjArray instead;

//macro andyWrite.C
{
   gROOT->Reset();
   TFile *f = new TFile("andy.root","recreate");
   TTree *T = new TTree("T","Andy test");
   TObjArray *ar = new TObjArray(1000);
   T->Branch("myBranch","TObjArray",&ar,32000,0);
   for (Int_t i=0;i<1500;i++) {
      Float_t x1 = gRandom->Rndm();
      Float_t y1 = gRandom->Rndm();
      Float_t x2 = x1+0.5;
      Float_t y2 = y1+0.5;
      TLine *line = new TLine(x1,y1,x2,y2);
      ar->Add(line);
      T->Fill();
   }
   T->Print();
   T->Write();
   f->Close();
   delete f;
}

//macro andyRead.C
{
   gROOT->Reset();
   TFile *f = new TFile("andy.root");
   TTree *T = (TTree*)f->Get("T");
   TObjArray *ar = 0;
   T->SetBranchAddress("myBranch",&ar);
   Int_t nentries = T->GetEntries();
   for (Int_t i=0;i<nentries;i++) {
      T->GetEntry(i);
      Int_t nlines = ar->GetEntries();
      if(i%100 == 0) printf("i=%d, nlines=%d\n",i,nlines);
      ar->Delete();
   }
}

Rene Brun



Andy Salnikov wrote:
> 
>   Hi all,
> 
>   yesterday I had a "fun" time, trying to make things work while writing
> and reading data in the TTrees. Basically, I needed a collection of
> items to be saved as a single object (branch) in the tree. I thought to
> use a TClonesArray as a persistent collection, 'cause everyone says that
> TClonesArray is superb. Fine. The first thing which I encountered was
> that an advertised TTree:Branch("branch",&clonesPtr,xxx,0) for
> TClonesArray does not seem to work at all when the splitlevel is zero.
> The branch is not get created (at least not in the tree). Is it expected
> to be that way? I solved this switching to BranchObject, calling
> TTree::Branch("branch","TClonesArray",&clonesPtr,xxx,0). That seemed to
> work, but I have been caught by the TTree::Print() output. It gave me
> something like that:
> 
> ************************************************************************
> ******
> *Tree    :testStream: ROOT output stream
> *
> *Entries :     1000 : Total  Size =    257352 bytes  File  Size =
> 38796 *
> *        :          : Tree compression factor =   6.63
> *
> ************************************************************************
> ******
> *Branch  :objectBranch : objectBranch
> *
> *Entries :     1000 : Total  Size =         0 bytes  File Size  =
> 0 *
> *Baskets :        0 : Basket Size =     32768 bytes  Compression=   1.00
> *
> *.......................................................................
> .....*
> *Branch  :listBranch : listBranch
> *
> *Entries :     1000 : Total  Size =    257352 bytes  File Size  =
> 38796 *
> *Baskets :        8 : Basket Size =     32768 bytes  Compression=   6.63
> *
> *.......................................................................
> .....*
> 
> The first branch seem to have no data at all. That scared me a bit and I
> have spend more time trying to figure out what's wrong with my code. I
> should not have done it, cause the data were actually there, only the
> output was misleading. Increasing number of event 10 times I got the
> expected output:
> 
> ************************************************************************
> ******
> *Tree    :testStream: ROOT output stream
> *
> *Entries :    10000 : Total  Size =   2861280 bytes  File  Size =
> 434051 *
> *        :          : Tree compression factor =   6.59
> *
> ************************************************************************
> ******
> *Branch  :objectBranch : objectBranch
> *
> *Entries :    10000 : Total  Size =    255591 bytes  File Size  =
> 40183 *
> *Baskets :        9 : Basket Size =     32768 bytes  Compression=   6.36
> *
> *.......................................................................
> .....*
> *Branch  :listBranch : listBranch
> *
> *Entries :    10000 : Total  Size =   2605689 bytes  File Size  =
> 393868 *
> *Baskets :       81 : Basket Size =     32768 bytes  Compression=   6.62
> *
> *.......................................................................
> .....*
> 
> More serious problem was awaiting me when I tried to read back what I
> have saved. I got an immediate crash when I tried to read the branch
> with the TClonesArray (created as above, in a single branch with
> splitlevel=0). After few hour spent in the debugger, I came to what I
> think is a bug in the TClonesArray code. The TClonesArray::Streamer()
> executes the following two lines:
> 
>          fKeep  = new TObjArray(nobjects);
>          Expand(nobjects);
> 
> Expand(), when "nobjects" is less than fSize (and this is the case),
> tries to delete the items [nobjects,fSize-1] from fKeep. And it crashes,
> just as anyone would expect, 'cause there are no allocated elements in
> fKeep behind "nobjects". My guess is that this must be fixed, but I
> myself cannot propose any fix, it look a bit complicated stuff for me.
> BTW, what is the design issue behind TClonesArray "being" and TObjArray
> and "having" TObjArray" at the same time. Is not this unnecessary
> complication of the design?
> 
>   Cheers,
>   Andy.



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET