I have a question, which may seem a bit random. It’s more of a shot in the dark, one possible explanation of a memory problem I’m having (see a little more explanation at the end of the post).
I have a class, Particle_Electron, which inherits from class Particle, which inherits from TLorentzVector. Is there anything inherhently wrong with this (compiled code using gcc 3.4.6, ROOT version 5.16, on either of SLC3 or SLC4):
Is this executed in interpreted or compiled code?
If it is interpreted, you must generate the dictionary for std::vector<Particle_Electron> (the interpreted version does not work properly with objects).
If it is compiled, you should try to run the program in gdb and see what the stack trace at the crash is.
As I said, this is compiled code, it contains several features I would not expect to work without compilation.
I have run it in gdb, and valgrind. The errors are not all that useful, except in suggesting that memory assignment has gone wrong somewhere, which causes a crash at some point further down the line. I am just trying to think of things which may go wrong, and this question about sorting a vector of what are essentially augmented TLorentzVectors occurred to me.
If it helps, I’ve attached the gdb backtrace below. Note that the program does not always crash in the same place. It always seems to be in a TBranch method, but I believe that is luck as much as anything as most of the program memory is probably associated with branches.
Line 55 of SignalAnalysis.C is where I call TChain::Process(TSelector*), in main(). AnalysisBase inherits from TSelector, and line 861 is a call to TBranch::GetEntry(). The actual line is just
The relevant declarations and branch-assignments in AnalysisBase.h are
// in AnalysisBase class declaration
TBranch *b_BunchNum; //!
// in AnalysisBase::Init(Tree*)
BunchNum = 0;
fChain->SetBranchAddress("BunchNum", &BunchNum, &b_BunchNum);
Humm … Since you are storing vector objects (and I assume that you are also storing the std::vector<Particle_Electron>), you need to load a directory for them (Technically, you only need to load a compiled collection proxy).
The required information would be loaded for each std::vector instance if, for that std::vector instance:
you generated the dictionary for a class whose has at least one data member of this type
for simple type (vector, vector), you loaded the pre-compiled dictionary (for example via gROOT->ProcessLine("#include ");
explicitly generate the dictionary (for example #pragma link C++ class vector<Particle_Electron>;
PS. The absence of this compile collection proxy leads to the use of an Emulated Collection proxy which has a different memory layout than the compile version.
Thanks for the reply. It’s not clear to me how much of this I need to implement. I myself don’t store any vectors of anything. I have a root file that contains vector and vector. I only read these. I make several vector<Particle_Electron>, map<TString, TH1F> and the like, but these are all transient. At the end, I only actually write histograms.
Given this, for the simple types, you suggest
I naturally already head the relevant files with #include , #include and so on. Is gROOT->ProcessLine() necessary on top of this? ie what does it add to a plain #include statement?
For the custom classes, I assume that to get your suggestion to work, I’d have to add a ClassDef() line to each class to declare its existence to ROOT? Is this necessary for something I don’t intend to write to a TFile? I’ve never managed to compile successfully with a ClassDef() in, but if this is important I can of course give it another go.
OK, so I’ve managed to get a simple example working, even including a vector of my own objects and all appears to work fine. Thanks for the suggestion. It will take some time to update my actual analysis code to fit this, and I can’t know until then whether the problem is actually fixed.
I have one quite big niggle remaining however. I apologise in advance for the potentially stupid and naive question here. Any clarification is much appreciated
So, unless I’ve really missed something, I can’t see anything in this that will actually solve the original problem. That is, I already had compiled code, compiled using g++. To the absolute best of my knowledge it’s clear of bugs, and it ran under most circumstances. But not in ROOT 5.16, when either reading std::vector<long/float> or sorting std::vector<Particle_Electron> seems to cause a problem. Am I completely missing the point about these libraries?
[quote]Is gROOT->ProcessLine() necessary on top of this? ie what does it add to a plain #include statement? [/quote]It depends where you put those plain #include statements. The point of the gROOT->ProcessLine is to make sure that these statements are seen by CINT (as opposed to the compiler). When CINT sees those include statements it knows to load the shared library that contains the dictionary and I/O helper for the (default) STL containers instances.
[quote]I’d have to add a ClassDef() line to each class to declare its existence to ROOT? [/quote]No, you do not. Totally uninstrumented classes are supported by the ROOT I/O.
[quote] I’ve never managed to compile successfully with a ClassDef()[/quote]Most likely you were missing the dictionary file (which is required when you use ClassDef) You need to run rootcint on your header files and compile and link the resulting dictionary files. For example for a class MyClass declared in a header file MyHeader.h, you would write a file myLinkDef.h file containing:#pragma link C++ class MyClass+;
// .. same for other classes in the library
and run rootcint:rootcint -f mydict.cxx -c MyHeader.h myLinkDef.hYou would do the same to generate the I/O (and CINT dictionary) for the class whether it has a ClassDef or not.
You do not need to generate the dictionary for the containing classes for this. You can request the dictionary for the STL container directly. For example put in your linkdef file:#pragma link C++ class std::vector<Particle_Electron>+;
#pragma link C++ class std::vector<float>+;
(as mention earlier the later is already generated as part of one of the shared library loaded when CINT sees #include ).