Hello,
I have a problem which I don’t understand. I am running over a Tree using a TSelector.
I am trying to Clone() a histogram - because I want to fill it for several different cuts. After cloning, I add it to fOutput to be able to run the code with Proof when processing a selector variable instead if a file is possible. In the Terminate method, I do SetOwner and clear the list. This should delete all created histograms properly.
However, when running the selector a second time over another chain, I get a segmentation violation. The funny thing is: if I replace the clone with “new TH1D(…)”, everything is fine. So I assume there is still some dependency of the cloned histogram with the original one and I might have a double delete or something similar. Is the histogram maybe stored in some ROOT dictionary?
The binnedControlPlots map maps a string to a histogram. Idea is that I want N control plots depending of the binning of our result. So the names will be something like lepton_pt_bin1_jetpt, …, lepton_pt_bin6_jetpt (it will not be only for 1 variable, thus I’m not using a vector).
So what is different between the commented code and the cloned = new TH1D line in terms of memory and/or ownership? (I would of course prefer to use Clone+Clear here, for example to copy the binning correctly)
Code:
std::map<std::string, TH1*> *binnedControlPlots;
template<class T>
T* Analysis::store(T* obj)
{
fOutput->Add(obj);
return obj;
}
TH1* Analysis::findOrClone(const char *name, TH1 *to_clone) {
auto it = binnedControlPlots->find(name);
if (it == binnedControlPlots->end()) {
cout << "Cloning " << to_clone->GetName() << " to get " << name << endl;
// TH1* cloned = static_cast<TH1*>(to_clone->Clone());
// cloned->Clear();
// cloned->SetName(name);
// cloned->SetTitle(name);
TH1 *cloned = new TH1D(name, name, to_clone->GetNbinsX(), to_clone->GetBinLowEdge(1), to_clone->GetBinLowEdge(to_clone->GetNbinsX()+1));
cloned->SetDirectory(0);
(*binnedControlPlots)[name] = store(cloned);
return cloned;
} else {
return it->second;
}
}
void Analysis::Terminate()
{
//...
fOutput->SetOwner();
fOutput->Clear();
}
The code is actually run like this - and the problem exists when processing the 2nd chain:
Analysis *selector = new Analysis();
chain1.Process(selector);
chain2.Process(selector);
Or maybe I am missing a way easier way to achieve what I want.