Segfault in branch creation with user defined class

Hi,

I have written a class that i would like to add to a tree (including doing the necessary rootcint, etc to make the dictionaries). I can do this if i am adding a single object from the class, but if i try to add multiple members of this class in a loop by using elements of a vector, the code segfaults. Here is a schematic example, if i need to add more detail and the real scripts, please let me know.

in MyAlg.h:

std::vector<MyClass *> *m_classVect;
MyClass *m_classElement;
TTree *m_nt;

in MyAlg.cxx, the following works:
m_nt = new TTree(TString(ntupleTreeName), “Cosmics”);
m_classElement = new MyClass();
m_nt->Bronch(TString(name+ “.”), “MyClass”,
&m_classElement,bsize,split);

But this segfaults:
m_nt = new TTree(TString(ntupleTreeName), “Cosmics”);
m_classVect = new std::vector< MyClass * >;

for(int i = 0; i< m_trackCollKeys.size(); i++){
m_classVect->push_back(new MyTrackColl());
m_nt->Bronch(TString(m_trackCollKeys[i]+ “.”), “MyClass”,
&m_classVect[i],bsize,split);
}

The segfault that occurs is:

0xffffe600
0xf65fc128 _ZN5TTree17BuildStreamerInfoEP6TClassPv + 0x34 [/common/atlas/kits/14.5.0/LCGCMT/LCGCMT_55b/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so]
0xf65fc37e _ZN5TTree6BronchEPKcS1_Pvii + 0x106 [/common/atlas/kits/14.5.0/LCGCMT/LCGCMT_55b/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so]
0xe7736ffd _ZN14CosNtupleMaker10BookNtupleEv + 0x4ad [/u/tompkins/testareaSL4/14.5.0.5/InstallArea/i686-slc4-gcc34-opt/lib/libHalfTrackDetective.so]
0xe7737f5f _ZN14CosNtupleMaker10initializeEv + 0xc3f [/u/tompkins/testareaSL4/14.5.0.5/InstallArea/i686-slc4-gcc34-opt/lib/libHalfTrackDetective.so]

Also, at the end of MyClass.h I’ve added:

#ifdef MAKECINT
#pragma link C++ vector<MyTrackColl*>;
#endif

I’m wondering if somehow i’m missing dictionaries for the vector or something? This happens both when i run inside of root or when i run outside with compiled c++ code (the segfault is an example of the later).

thanks for your time!
~lauren

Hi,

The address ‘&m_classVect[i]’ is NOT a stable value. Each time the vector resize itself, the actual location of m_classVect[i] can move. The TTree must have a stable address (it records this value and will look for the object there.

However this does not seem to explain the stack trace you show. I do not have quite enough information to ‘guess’ what the problem is. Could you provide a complete running example?

Also do not use the method ‘Bronch’ directly use Branch.

In modern version of ROOT you can do:

m_nt->Branch(TString(name+ "."),&m_classElement,bsize,split);I.e. Branch can automatically detect the data type.

Cheers,
Philippe.

Hi Philippe,

Thank you for the response. I found a typo in my Root stand-alone version of the macro which was causing it to crash. (I was accidentally initializing my vector m_classVect to 0 and then trying to initialize it to new). The stack trace that i sent in the previous entry is from within the Atlas software and it still exists. I’ll see if someone in my collaboration can tell me why its giving me that segfault (BuildStreamer) because it might be particular to Atlas.

However, i have a question on how in principle i can create branches in root. I want to have an executable that is flexible enough so that it adds N branches of the same class, where N is an input to the executable. I was trying to do that using a vector, but you say that it is not possible since the vector is variably sized. What else could i use to give me that functionality?

I’ll add that the root standalone version does crash when i do tree->Fill(). I attach the files for the standalone version of the code. Ignore it if it is only crashing because of my use of vectors.

cheers,
~lauren
rootmacros.tar (50 KB)

Hi Lauren,

Your example does not crash on my platform. Note that I am not sure how you are running it. The way I did is:root [0] .L MyTrackColl.cxx+ root [1] .L test.C+ Info in <TUnixSystem::ACLiC>: creating shared library /var/tmp/track/./test_C.so root [2] testit();

In you file mylinkdef.h (if you are using it), you should use: #pragma link C++ class MyTrackColl+;note the trailing +.

In your test.C you can try: int max_coll = 200; // or some number strictly greater than the maximum number of track collection. m_track = new std::vector< MyTrackColl * >(max_coll);

Cheers,
Philippe.

Thanks, it works now!