Vectors and maps in TBranch::SetBranchStatus

Hi all,

I’ve been running into some problems using vectors and maps, and have tried following the advice posted here, but unfortunately without much luck.

I’ve made a loader.C class, which loads all the dictionaries I think I need:

#include <vector>
#include <map>
#include <utility>
#ifdef __MAKECINT__
#pragma link C++ class vector<double>+;
#pragma link C++ class vector<float>+;
#pragma link C++ class vector<int>+;
#pragma link C++ class map<int,vector<int> >+;
#pragma link C++ class map<int,vector<double> >+;
#endif

I then begin the root session with .L loader C+ as the first command. I then load my ntuples and my root macro, which contains lines such as

vector<int>	*triggerDecisions;
tree->SetBranchAddress("triggerDecisions", &triggerDecisions);

and

map<int,vector<int> >      *l3DetIds;
tree->SetBranchAddress("l3DetIds", &l3DetIds);

With this code I have two (known) problems. The first comes in the form of these error messages:
Error in TTree::SetBranchAddress: The class requested (vector<int,allocator >) for the branch “triggerDecisions” refer to an stl collection and do not have a compiled CollectionProxy. Please generate the dictionary for this class (vector<int,allocator >).
I’m confused about why I’m getting them, when I thought I’d generated these dictionaries in my loader.C file.

The second comes in the form of a segmentation fault when I try to access (*l3DetIds).second.

Just for reference, I’m running version 5.18 that came precompiled with CMSSW.

Any help would be greatly appreciated.

Hi,

The dictonary for vector of int, float and double are pre-generated and can not be regenarated (i.e. when creating your dictionary you should have seen a note about vector, etc.).

In ROOT v5.20, the loading of this pre-generated dictionary has been automated. In ROOT v5.18, you need explicitly load it by asking the interpreter to execute #include . E.g.root [] #include <vector>

Cheers,
Philippe.

Hi Philippe,
Thanks for the quick reply. After I followed your advice, I got the first problem taken care of, but I’m still having a problem with my maps. The two commands in the interpreter I’m using right now are

root [1] #include <vector>
root [2] #include <map>

and I can now access all members that are of type vector. Unfortunately, I still have segfaults when I try to access the .first and .second members of my maps. I’ve tried asking the interpreter to execute, e.g.

#pragma link C++ class map<int,vector<int> >+; 

as well, but that didn’t really help.

Is there anything else I should be loading or passing through the interpreter to get this problem resolved?

Thanks,
Tom[/quote]

Hi,

Please note that you must initialize the pointer(s), i.e.:map<int,vector<int> > *l3DetIds = 0; tree->SetBranchAddress("l3DetIds", &l3DetIds); If you do not then ROOT is attempting to write to write random memory is pointed to by l3DetIds.

Cheers,
Philippe.

Hi Philippe,

Thanks again for the response. Unfortunately, I think my problem is more with the data type than it is with the initialization (I still get the same segfault after trying to initialize l3DetIds to zero or as a new map<int,vector >). The macro was generated using a script similar to TTree::MakeClass on the files I’m trying to run on.
I thought the declaration

and the SetBranchAddress command would allow my macro to access the existing *l3DetIds data member from the input root file. Would I still have the problem of trying to write to random memory with a non-initialized data member in this case?

Cheers,
Tom

[quote]The macro was generated using a script similar to TTree::MakeClass on the files I’m trying to run on.[/quote]Humm … Important detail :slight_smile:. The skeleton generated by MakeClass but the TTree in a mode where you can quickly retrieve the individual elements of the object but can not retrieve the object themselves [This setting is done via the call to SetMakeClass(1) ]. This is because MakeClass was implemented with the case where you would not have access to any C++ code representing the object when trying to access the TTree (via MakeClass).

Thus to solve the problem you might to only comment out the line looking like fChain->SetMakeClass(1); However this will also invalidate all the SetBranchAddress that do not use actual C++ objects (but instead relies on the object decomposition). If you need both, you probably should try MakeProxy instead of MakeClass (and use the latest possible release of ROOT you can:)).

Cheers,
Philippe.