Help debugging an access violation during TTree output

Hi,
I need some help helping myself. I’ve got a pretty simple set of root classes that I’m trying to write out:

[code]class EventInfo
{
public:
int nJets;
std::vector Jets;
};

class JetInfo
{
public:
double defaultTagWeight;
TLorentzVector v;
};[/code]
I create a pretty plane file and tree:

m_rootTree = new TTree ("usertree", "A tree man"); m_event = new EventInfo(); m_rootTree->Branch("event", "EventInfo", &m_event, 6400, 99); m_rootTree->SetAutoSave();

and do the normal sorts of things to fill it:

m_event->nJets = nJets; m_event->Jets.clear(); loop over jets: JetInfo info; info.v.SetPtEtaPhiM(jet.pt(), jet.eta(), jet.phi(), jet.m()); info.defaultTagWeight = jet.getFlavourTagWeight(); m_event.push_back(info); m_rootTree->Fill();
But when I run I get an access violation under the TTree::Fill on the first event:

#0 0xb6e0707c in TStreamerInfo::WriteBufferAux<TVirtualCollectionProxy> () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libRIO.so #1 0xb6e048c0 in TStreamerInfo::WriteBufferSTL () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libRIO.so #2 0xb646b585 in TBranchElement::FillLeaves () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so #3 0xb6465bed in TBranch::Fill () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so #4 0xb646acb6 in TBranchElement::Fill () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so #5 0xb646acd4 in TBranchElement::Fill () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so #6 0xb646acd4 in TBranchElement::Fill () from /opt/atlas/software/15.2.0/15.2.0/LCGCMT/LCGCMT_56a/InstallArea/i686-slc4-gcc34-opt/lib/libTree.so #7 0xb64b30ac in TTree::Fill ()

This smells to me like I’ve forgotten some class dictionary (I’m using the ATLAS reflex infrastructure to generate these dictionaries). But I think I’ve included everything I need.

One odd thing to note (perhaps I do have the dictionaries?): If I don’t actually push_back any jets, then it writes out just fine. Further, when I inspect the TTree with TBrowser I can see the elements of TLorentzVector and decay length all there just fine (but, of course, empty!).

How can I debug this to see what I’ve done wrong? Many thanks!

-Gordon

P.S. I would have included a small snippit of code to demo the problem, but of course it always works when I try to distil it down. Sorry! There is something about what I’m doing in combination with the ATLAS envrionment that is causing this.

Hi Gordon,

You might need to add an explicitly dictionary for std::vector.

Cheers,
Philippe.

Hi Philippe,
I would expect that I did - and I’d added one (or at least, I’m pretty sure I added one).

Looking at the call-stack can you tell it isn’t getting used? Since I was doing full splitting I figured that I wouldn’t expect to see any streamer calls on there…

Cheers, Gordon.

Hi Gordon,

There is not streamer involved indeed. However the wrapper around the collection are and the last part of the crash is:#0 0xb6e0707c in TStreamerInfo::WriteBufferAux<TVirtualCollectionProxy> () which says there is something wrong with the access to the collection. I was hoping that the problem was as simple as the system attempting to use an ‘emulated collection proxy’ over a compiled collection proxy which is doomed to fail (and that we still need to add more protection against).

By running with gDebug = 5; you would also get more details and where exactly the problem occurs. You might also try to run via valgrind.

Cheers,
Philippe.

Ok - I will run with gDebug=5. Is there a line in there I can search for that indicates it is looking for a particular proxy?

[quote]Ok - I will run with gDebug=5. Is there a line in there I can search for that indicates it is looking for a particular proxy?[/quote]I don’t think so. Instead we should know which class/data member it dies on.

Cheers,
Philippe.

Hi,
Hmmm. Ok, here is all it wrote out before it crashed:

WriteBuffer, class:EventInfo, name=nJets, fType[0]=3, TStreamerBasicType, bufpos=76, arr=0xc4b4470, offset=0 WriteBuffer, class:JetInfo, name=defaultTagWeight, fType[0]=8, TStreamerBasicType, bufpos=92, arr=0x11651a00, offset=0 WriteBuffer, class:TObject, name=fUniqueID, fType[0]=13, TStreamerBasicType, bufpos=87, arr=0x11651a00, offset=12 WriteBuffer, class:TObject, name=fBits, fType[1]=15, TStreamerBasicType, bufpos=83, arr=0x11651a00, offset=16 WriteBuffer, class:TObject, name=fUniqueID, fType[0]=13, TStreamerBasicType, bufpos=90, arr=0x11651a00, offset=0 WriteBuffer, class:TObject, name=fBits, fType[1]=15, TStreamerBasicType, bufpos=86, arr=0x11651a00, offset=0

So it had done the JetInfo default weight guy, everything in tobject. And now it is starting on TLorentzVector perhaps!?! I’ve got TLorentzVector listed as being generated in my reflex dictionary guy.

I should have noted - I set gDebug = 5 just before the call to TTree::Fill. So during the booking of the histogram nothing was written out.

[quote] I’ve got TLorentzVector listed as being generated in my reflex dictionary guy.[/quote]This is bad and is likely to be your problem. genreflex prior to v5.24 does not handle class with a ClassDef correctly. Anyway ROOT provide a perfectly valid dictionary for TLorentzVector :slight_smile:

Cheers,
Philippe.

PS. The output leads me to believe that only the TObject part of TLorentzVector which seems like your setup make ROOT not properly recognize TLorentzVector …

Interesting.

So I had TObject and TLorentzVector in my dictionary. I removed both and left only EventInfo, JetInfo, and vector. THe # of lines before a crash is less now:

WriteBuffer, class:EventInfo, name=nJets, fType[0]=3, TStreamerBasicType, bufpos=76, arr=0xc4cb430, offset=0 WriteBuffer, class:JetInfo, name=defaultTagWeight, fType[0]=8, TStreamerBasicType, bufpos=92, arr=0xc6bec00, offset=0 WriteBuffer, class:TObject, name=fUniqueID, fType[0]=13, TStreamerBasicType, bufpos=87, arr=0xc6bec00, offset=0 WriteBuffer, class:TObject, name=fBits, fType[1]=15, TStreamerBasicType, bufpos=83, arr=0xc6bec00, offset=0

Comparing that to the debug output above it makes me think that perhaps there was something very odd going on with TObject being written out twice.

However, the crash happens in the same place.

I’m using ROOT 5.22.

So - how does it fail to recognize TLorentzVector? I’m using it in my code, so it is certianly linked in!

[quote]So - how does it fail to recognize TLorentzVector? I’m using it in my code, so it is certianly linked in![/quote]Yes, but it does not mean that the dictionary/TClass infrastructure is able to properly relate the TLorentzVector object to correct meta data. A rough example of such a failure is the case where you inherit from TObject but do NOT add a ClassDef. In such a case when the infrastructure execute the equivalent of:MyClass *myobj = new MyClass; TClass *cl = myobj->IsA(); // Try to know the real type from the TObject pointerwithout the ClassDef ‘myobj->IsA()’ return TObject::Class() (instead of MyClass::Class()).

hi Gordon,

What doesTClass::GetClass("JetInfo")->GetStreamerInfo()->ls(); print in your case?

Philippe.

Hmmm. Ok, we are getting further. During my testing I’d changed the definition of JetInfo to:

class JetInfo { double defaultTagWeight; TLorentzVector v; };

The streamer dump told me that. WHen I put it back to what I have listed above, the crash goes away.

Should the above cause a crash?

Nope - something is still wrong. Here is the output of the TClass line you had above:

StreamerInfo for class: JetInfo, checksum=0xc586d21a TLorentzVector BASE offset= 0 type= 0 A four vector with (-,-,-,+) metric i= 0, TLorentzVector type= 0, offset= 0, len=1, method=207259264

note there is no defaultTagWeight now! And, indeed, in the root TTree there is no defaultTagWeight in the TBrowser window either. How did it get the wrong streamer like that?

Hi
So now I’m very confused. If I comment out the “: public TLorentzVector” then the streamer has the defaultTagWeight variable in it and it is correctly written to the root tree. If I uncomment it then that isn’t written. What the heck is going on with the reflex processor?

I should mention that my stand-alone version of this worked just fine, so this could well be a ATLAS config problem. I’ll send email to that mailing list tomorrow.

And there is the crash when TLV is a member of the class rather than its superclass.

Hi Gordon,

[quote]So now I’m very confused. If I comment out the “: public TLorentzVector” then the streamer has the defaultTagWeight variable in it and it is correctly written to the root tree. If I uncomment it then that isn’t written. What the heck is going on with the reflex processor?

I should mention that my stand-alone version of this worked just fine, so this could well be a ATLAS config problem. I’ll send email to that mailing list tomorrow.
[/quote]The problem is with genreflex older than v5.24 (i.e yesterday’s release). When a class inherits from TObject (directly or indirectly as in your case), the class MUST have a ClassDef which the older genreflex can NOT handle. So with your version of ROOT you can NOT inherit from TLorentzVector; otherwise you class and your object will all appear to the system (including the TTree) as if they were TLorentzVector and/or an empty class deriving from TLorentzVector (the output 2 post above is exactly what expect!).

In the standalone test, you probably are using rootcint which properly know how to handle this case and probably forced you to add the ClassDef! :slight_smile:

Cheers,
Philippe.

I think I’ve gotten a conclusion to this error with a huge amount of help from Axel and Philippe.

I’m using version 5.22, and genreflex and ClassDef don’t work all that well there. This includes both versions of JetInfo I’ve listed above. Both should work in 5.24 (but I’ve not tested that).

One possible workaround for the version of JetInfo with TLorentzVector as a member variable is to turn the split level to 0.

Thanks for the help!