RE: Problem reading branches of structs

From: Andrea Bocci <Andrea.Bocci_at_cern.ch>
Date: Wed, 27 Apr 2005 15:44:49 +0200


> Andrea,
>
> I do not understand your argument that:
> "gcc keeps the struct fields aligned to 4 bytes boundary"
> This is impossible with your struct.

Well, in the comiled code, sizeof(bTagInfo) is 68, while in ROOT/CINT it is 72. So, different packing and allignement is applied.

> Could you replace
>
> tree->SetBranchAddress ("bTagInfo", &info);
> by
> tree->SetBranchAddress ("bTagInfo", &info.jet_E);

But this would completely de-allign (either of 4 or 8 bytes) the struct in memory with the one in the root file.

> Note that we keep discouraging users to use structs instead
> of classes. With a class and its dictionary, you will simplify
> your interface when defining the branch: no need to specify
> the names of the data members since they are already known
> by the dictionary, and in addition you will get support
> for correct alignment of members in the class.

I know, and I usually do it, but I wanted a simpler solution, without the need of an external (however simple) library. I guess that saying that this is not supported is an acceptable solution - I can either compile all my applications (I usually do it), or use a class with a dictionary. Anyway:

> if you do not solve your problem, please send the shortest
> possible system reproduding it.

here is a simple tet case, which show the same behaviour. Again, sizof(XData) is 12 with gcc, but 16 with root.

struct XData {
  unsigned int an_int;
  double a_double;
};

#endif // XData_h


#include "XData.h"

void write (void) {
  TFile* file = new TFile("test.root", "RECREATE");   TTree* tree = new TTree("Test", "Test tree for a simple structure");

  XData data;
  tree->Branch("XData", &data, "an_int/i:a_double/D");

  for (unsigned int i=0; i < 10; i++) {
    data.an_int = i;
    data.a_double = i;
    tree->Fill();
  }
  tree->Write();
  file->Close();
}

int main (int argc, const char** argv) {   write();
  return 0;
}


and

#include <TFile.h>
#include <TTree.h>

#include "XData.h"

void read (void) {
  TFile* file = new TFile("test.root");
  TTree* tree = (TTree*) file->Get("Test");

  XData data;
  tree->SetBranchAddress("XData", &data);

  for (unsigned int i=0; i < 10; i++) {
    tree->GetEvent(i);7
    cout << data.an_int << '\t' << data.a_double << endl;   }
  file->Close();
}

int main (int argc, const char** argv) {   read();
  return 0;
}


compiled with
  g++ -O2 $(root-config --cflags --libs) write.cc -o write   g++ -O2 $(root-config --cflags --libs) read.cc -o read using GCC 3.2.3 and ROOT 3.10/02 (I've tried ROOT 4.x, same behaviour).

If I do:
  ./write
  ./read

I get:

  0       0
  1       1
  2       2
  3       3
  4       4
  5       5
  6       6
  7       7
  8       8
  9       9


If I do:
  ./write
  root read.cc

I get:
  Processing read.cc...

  0       3.39519e-313
  1       3.44819e-313
  2       3.44824e-313
  3       3.44827e-313
  4       3.44829e-313
  5       3.44831e-313
  6       3.44832e-313
  7       3.44833e-313
  8       3.44835e-313
  9       3.44835e-313

which doesn't look correct...

I get something similar if I do:
  root write.cc read.cc

While with:
  root write.cc
  ./read

I get:
  Processing write.cc...

  0       0
  1       0
  2       0
  3       0
  4       0
  5       0
  6       0
  7       0
  8       0
  9       0

(prompt lines removed, of course).

Thanks for your time and replies !

.Andrea. Received on Wed Apr 27 2005 - 15:45:02 MEST

This archive was generated by hypermail 2.2.0 : Tue Jan 02 2007 - 14:45:07 MET