Ownership: Cloning a histogram vs new TH1D

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.

Solved the problem by rewriting it a bit. Don’t know what exactly solved the problem, but maybe it was a TH1::AddDirectory(false);.

However, still dont understand why cloning wasn’t working.