Read out of struct from TTree doesn't work properly

Hi,

I’ve got a TTree; it has one branch to a struct and some ints. This TTree is filled and written to file. So far, no problem. The problem is, that one -or perhaps more- of the fields of the struct are not written or filled correctly, so depending weather I read the TTree from CINT or with a separate compiled program, the values for this field is not the values I filled in originally, but they are different using the two different ways of reading.

The struct is defined as:
typedef struct
{
Double_t phi;
Double_t theta;
Double_t beta;
Int_t ID;
Int_t nEl;
Int_t ss[17];
Float_t qdc[17];
Float_t tdc[17];
Double_t vertex[3];
Double_t phiIn;
Double_t thetaIn;
Double_t betaIn;
Int_t nElIn;
Int_t ssIn[17];
Double_t vertexIn[3];
Double_t momentum;
}track;

the Branch-call is:
tmpTree->Branch(“Track1”,&Track[0],“phi/D:theta:beta:ID/I:nEl:ss[17]/I:qdc[17]/F:tdc[17]/F:vertex[3]/D:phiIn/D:thetaIn:betaIn:nElIn/I:ssIn[17]/I:vertexIn[3]/D:momentum/D”);

and the problem occurs for the field “momentum” and sometimes also fir “phiIn”, “thetaIn” and “betaIn”. The ones, that are defined after the arrays. May that cause the problem?

Ehrhardt

Hi Erhardt,
the memory position of the struct members is not defined in C++ - it is left to the compiler and platform to decide what the memory distance between the members is (padding). While CINT tries to simulate the compiler’s behavior it often fails. It is safer to always and only use compiled classes / structs as the memory address for structured i/o.
Axel.

Oh, yes, I did that. I suspected that already. But the problem is, that this occurs not only with CINT but also in a compiled program. The only difference is in the values it reads. For the compiled program it is something like 6.95324e-310 or so and in CINT it goes from “nan” to “inf” and so on.
Always, when there is a problem in CINT, I try it first in a regularly compiled program.
But here the error also appears.
By the way, the filling of the tree is also done in a compiled program, but that was with a different version (5.11 instead of 5.14.00e)

Ehrhardt

Hi,

In this case, you need TTree::Branch to emulate(or guess) the compiler (and CINT’s) layout. This almost always fails when you do not order the data member by decreasing sizeof. In your case you have 2 doubles followed by 5 int/float followed by doubles; depending on the compiler there might or might not be a padding before this last doubles.

Anyway your best bet is not only to compile but also to use the object oriented Branch call. Aka track *track_ptr = new track; tmpTree->Branch("Track1",&trk_ptr);

Cheers,
Philippe

1 Like