A bug in TTree (can't be...)

I have a problem in a large piece of code, but I could track it down to the following example:

[code]#include
#include <TTree.h>

using namespace std ;

struct resultsStruct
{
double aDouble ;
int anInt ;
double anotherDouble ;
} ;

void testStruct()
{
struct resultsStruct results ;

results.aDouble = 1.2 ;
results.anInt = 3 ;
results.anotherDouble = 4.5 ;

TTree * treeResults = NULL ;

treeResults = new TTree(“treeResults”, “treeResults” ) ;
treeResults->Branch(“branchResults”, &results, “aDouble/D:anInt/I:anotherDouble/D”) ;

treeResults->Fill() ;

TFile * file = new TFile(“test.root”, “RECREATE”) ;
treeResults->Write() ;
file->Close() ;

}[/code]

If I read back the file and do a scan (or fill a histogram) I get :

[quote]$ root -l test.root
root [0]
Attaching file test.root as _file0…
root [1] treeResults.Scan()


  • Row * aDouble * anInt * anotherDo *

  •    0 *       1.2 *         3 *         0 *
    

[/quote]
The last value (the value of anotherDouble) is now zero! Actually, in my larger code the last value of the tree is a random number. If I invert the order of the variables in the struct declaration (and in the branch as well), placing the interger value as the last one, everything looks ok. This is wierd, but so simple that I’m obviously missing something…
I attach a working example just for convenience:

[code]#include
#include <TTree.h>

using namespace std ;

struct resultsStruct
{
double aDouble ;
double anotherDouble ;
int anInt ;
} ;

void testStruct()
{
struct resultsStruct results ;

results.aDouble = 1.2 ;
results.anotherDouble = 4.5 ;
results.anInt = 3 ;

TTree * treeResults = NULL ;

treeResults = new TTree(“treeResults”, “treeResults” ) ;
treeResults->Branch(“branchResults”, &results, “aDouble/D:anotherDouble/D:anInt/I”) ;

treeResults->Fill() ;

TFile * file = new TFile(“test.root”, “RECREATE”) ;
treeResults->Write() ;
file->Close() ;

}
[/code]

This time the result appears to be correct!

[quote]$ root -l test.root
root [0]
Attaching file test.root as _file0…
root [1] treeResults.Scan()


  • Row * aDouble * anotherDo * anInt *

  •    0 *       1.2 *       4.5 *         3 *
    

[/quote]

Amazed: thanks for any reply.

Dario

[quote]If I invert the order of the variables in the struct declaration (and in the branch as well), placing the interger value as the last one, everything looks ok. This is wierd, but so simple that I’m obviously missing something…
[/quote]This is known limitation of the leaflist method, this method is not smart enough to determine properly in all the cases the layout of the data member (in particular the (probable) padding between anInt and anotherDouble).
If you have to use the leaflist method you should try to
a) put only one variable per branch
b) sort the variable from the largest to the smallest.
But best of all is to compile (for example with ACLiC) the struct and use the class/struct based method:

struct resultsStruct *results_ptr = new resultsStruct; ..... treeResults->Branch("branchResults", &results_ptr);

Cheers,
Philippe.