A bug in TChain?

I may have stumbled on a TChain bug of some sort…

I have 3 root files, which I chain, and run a script on. Here’s the content of the script:

testchain.C –

void testchain(TTree* ptree) //threshold at 50keV, by default
{
  TBranch *event  =ptree->GetBranch("event"); //get the event branch
  TLeaf *cn=event->GetLeaf("cn");
    
  int nentries=ptree->GetEntries();

  int i=0;
  do{
    ptree->GetEntry(i);
    i++;
    std::cout << "got here\n";
  } while(cn->GetValue()!=0); 
  return;
}

Here are my actions, and the subsequent seg. fault:

root [0] TChain a("ptree");a.Add("/home/aregjan/data_vx511/root_all/2012_08_23_13_41_06_secondary_[145]_plus15_lowth.root")                    
(Int_t)3
root [1] .L testchain.C                                                                                                             
root [2] testchain(ptree)                                                                                                                      
got here

 *** Break *** segmentation violation

...blah blah blah deleted...

Both the script, and the operation are quite correct, right?

Now, here’s how you can avoid the segfault:

a) instead of chaining 3 root files, chain only the first two:

root [0] TChain a("ptree");a.Add("/home/aregjan/data_vx511/root_all/2012_08_23_13_41_06_secondary_[14]_plus15_lowth.root")                     
(Int_t)2
root [1] .L ../scripts/testchain.C                                                                                                            
root [2] testchain(ptree)                                                                                                                     
got here
root [3] 

and it runs fine. “Ah , it’s probably a problem with the 3rd root file!”, you’ll say. BUT –

b) you can also “fix” the problem by commenting the ptree->GetEntries() line in the script itself. If you do this, you can still chain over 3 root files and have the script run successfully:

root [0] TChain a("ptree");a.Add("/home/aregjan/data_vx511/root_all/2012_08_23_13_41_06_secondary_[145]_plus15_lowth.root")                    
(Int_t)3
root [1] .L ../scripts/testchain_modified.C                                                                                                             
root [2] testchain(ptree)                                                                                                                      
got here
got here
got here
got here
got here
root [3] 

So, what’s going on?

p.s. before you ask, I did try this by putting the 3rd root file alone in the chain, and everything runs fine.
So I doubt that it’s something wrong with the file…

And I forgot to mention, I am running version 5.28/00 (I know, old).

Tried this with version 5.32/00, same exact problem.

Also, here’s more info about the tree itself:

root [0] TChain a("ptree");a.Add("~/data_vx511/root_all/2012_08_23_13_41_06_secondary_[145]_plus15_lowth.root")                    
(Int_t)3
root [1] ptree->Print()
******************************************************************************
*Chain   :ptree     : ~/data_vx511/root_all/2012_08_23_13_41_06_secondary_1_plus15_lowth.root *
******************************************************************************
******************************************************************************
*Tree    :ptree     : event data                                             *
*Entries : 62836558 : Total =      2262285885 bytes  File  Size = 1565463717 *
*        :          : Tree compression factor =   1.45                       *
******************************************************************************
*Br    0 :event     : samples/i:cn/i:min_i/i:min/i:E/F:Ec/F:Ecp/f:Ped/F:PSD/F*
*Entries :62836558 : Total  Size= 2262285513 bytes  File Size  = 1565445562 *
*Baskets :     1812 : Basket Size=    4781056 bytes  Compression=   1.45     *
*............................................................................*
******************************************************************************
*Chain   :ptree     : ~/data_vx511/root_all/2012_08_23_13_41_06_secondary_4_plus15_lowth.root *
******************************************************************************
******************************************************************************
*Tree    :ptree     : event data                                             *
*Entries : 60242135 : Total =      2168884890 bytes  File  Size = 1500373460 *
*        :          : Tree compression factor =   1.45                       *
******************************************************************************
*Br    0 :event     : samples/i:cn/i:min_i/i:min/i:E/F:Ec/F:Ecp/f:Ped/F:PSD/F*
*Entries :60242135 : Total  Size= 2168884518 bytes  File Size  = 1500355513 *
*Baskets :     1793 : Basket Size=    4784640 bytes  Compression=   1.45     *
*............................................................................*
******************************************************************************
*Chain   :ptree     : ~/data_vx511/root_all/2012_08_23_13_41_06_secondary_5_plus15_lowth.root *
******************************************************************************
******************************************************************************
*Tree    :ptree     : event data                                             *
*Entries : 61760060 : Total =      2223531213 bytes  File  Size = 1538489324 *
*        :          : Tree compression factor =   1.45                       *
******************************************************************************
*Br    0 :event     : samples/i:cn/i:min_i/i:min/i:E/F:Ec/F:Ecp/f:Ped/F:PSD/F*
*Entries :61760060 : Total  Size= 2223530841 bytes  File Size  = 1538471207 *
*Baskets :     1804 : Basket Size=    4784640 bytes  Compression=   1.45     *
*............................................................................*

Hi,

Never manipulate TLeaf and TBranch object when processing TChain. Or least you need to be careful. Those object will be deleted and recreated at each file boundary.

You may want to use something like:

[code]
void testchain(TTree* ptree) //threshold at 50keV, by default
{
for(Long64_t entry = 0; entry < ptree->GetEntriesFast(); ++entry) {
if (ptree->GetEntry(i) < 0) break;
std::cout << “got here\n”;

   TBranch *event  =ptree->GetBranch("event"); //get the event branch
   TLeaf *cn=event->GetLeaf("cn");

   if (cn->GetValue() == 0) break;
}
return;

}[/code]

or more efficiently

[code]struct Data
{
int samples;
int cn;
int min_t;
int min;
float E;
float Ec;
float Ecp;
float Ped;
float PSD;
};

void testchain(TTree* ptree) //threshold at 50keV, by default
{
Data data;
ptree->SetBranchAddress(“event”,&data);
for(Long64_t entry = 0; entry < ptree->GetEntriesFast(); ++entry) {
if (ptree->GetEntry(i) < 0) break;
std::cout << “got here\n”;
if (data.cn == 0) break;
}
ptree->ResetBranchAddresses();
return;
}
Cheers,
Philippe.

Dear Philippe, thank you for the extended response. I do understand how to set the branch addresses, as in your 2nd example. However, in the 1st example I am not sure I understand how it’s more safe than what I do. Is it safer because it allows me to avoid cn->GetValue() in case of a ptree error?

Btw, when I use TTree::GetEntriesFast() I always get something like 1234567890. What is it supposed to do, really?

[quote]is it safer because it allows me to avoid cn->GetValue() in case of a ptree error?[/quote]No. It is safer because it retrieve the address of the branch at each iteration and thus always get the current address of the branch no matter which file the TChain is in.

[quote]Btw, when I use TTree::GetEntriesFast() I always get something like 1234567890. What is it supposed to do, really?[/quote]It returns an arbitrary large value until the last file is started to be read (at which point it starts return the real number of entries). This is to avoid having to open every single file in the TChain (and then closing them) even before you start iterating through it.

Cheers,
Philippe.

Ok, now I get it. Thanks again.