Workaround for TChain bug in ROOT 2.22.10

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Tue Aug 24 1999 - 09:56:48 MEST


I reported a bug with "class TChain" a few days ago in which the
analysis skeleton generated by "TTree::MakeClass" didn't work when
instantiated with a TChain* (see
http://root.cern.ch/root/roottalk/roottalk99/1944.html).

I have a fix and a workaround for this bug, which I thought I would
share with the list.

The problem is in `TREE_Chain.cxx'.  Please note that this bug can
affect *all* uses of a "TChain" in your analysis code, and is *not*
limited to the code generated by "TTree::MakeClass".

I have a patch to the source code which fixes this bug which I would be
happy to share with whomever may need it.  However, using my patch would
require you to patch your sources and rebuild ROOT.  You can do this if
you wish, but there is an easier workaround that doesn't require you to
rebuild ROOT, which is the subject of the rest of this e-mail.  Besides,
the ROOT Team will probably come up with a more elegant solution than
mine in the next release of ROOT.

The executive summary for the workaround is that you must use the method
"TChain::SetBranchAddress" instead of the methods "TTree::GetBranch"
followed by "TTree::SetAddress".

For example, consider the following example, in which we write to stdout
an element from a branch named "foo" (consisting of a float) which comes
from a "TTree" named "T" (which consists of a "TChain" of files):


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                             begin example
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   TChain* tree = new TChain( "T" );
   tree->Add( "foo-1.root" );
   tree->Add( "foo-2.root" );
   tree->Add( "foo-3.root" );
   tree->Add( "foo-4.root" );
   
   float foo;

   // The next two lines are broken.
   TBranch* b_foo = tree->GetBranch( "foo" );
   b_foo->SetAddress( &foo );

   size_t nevent = static_cast< size_t >( tree->GetEntries() );
   for ( size_t i = 0; i < nevent; ++i )
   {
      tree->GetEntry( i );
      cout << "foo = " << foo << endl;
   }
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                              end example
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


Notice the comment, above, indicating which of the two lines are broken
for "class TChain".  The workaround is to use the single method
"TChain::SetBranchAddress" instead, as follows:


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                             begin example
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   TChain* tree = new TChain( "T" );
   tree->Add( "foo-1.root" );
   tree->Add( "foo-2.root" );
   tree->Add( "foo-3.root" );
   tree->Add( "foo-4.root" );
   
   float foo;

   tree->SetBranchAddress( "foo" , &foo );

   size_t nevent = static_cast< size_t >( tree->GetEntries() );
   for ( size_t i = 0; i < nevent; ++i )
   {
      tree->GetEntry( i );
      cout << "foo = " << foo << endl;
   }
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                              end example
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


Unfortunately, although this is a trivial way to workaround the bug, the
code generated by "TTree::MakeClass" uses the first (broken) method.
So, you will have to edit the automatically generated code by hand.
Interestingly enough, the code generated by "TTree::MakeCode" does
generate correct code (it uses "TChain::SetBranchAddress").

There was another proposed fix for this bug (see
http://root.cern.ch/root/roottalk/roottalk99/1810.html), but I have
confirmed that this does not work for ROOT 2.22.10.

--
Matthew D. Langston
SLD, Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU



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