TFile and TDirectory with smart pointers

Dear all,

after reading the ROOT chapter about Object Ownership and experimenting with code I have one remaining question:
How to create a directory in a TFile and store it in a smart pointer (like boost::scoped/shared_ptr).

My code is at follows:

boost::shared_ptr<TH1F> h_et; boost::shared_ptr<TH1F> h_diElectronMass; boost::shared_ptr<TH2F> h_ptRel_vs_DRmin; boost::shared_ptr<TFile> outputfile; boost::shared_ptr<TDirectory> testingDirectory;
Creating histograms in the constructor of my analysis class

Analysis::Analysis() : h_et(new TH1F("electron_et", "electron_et", 100, 0, 100)), h_diElectronMass(new TH1F("diElectronMass", "diElectronMass", 500, 0, 500)), h_ptRel_vs_DRmin(new TH2F( "ptRel_vs_DRmin", "ptRel_vs_DRmin", 100, 0, 1, 300, 0, 300)), outputfile(new TFile( "egammaAnalysis.root", "RECREATE")), testingDirectory(outputfile->mkdir("testing")) { for (unsigned int cut = 0; cut < TTbarEPlusJetsSelection::NUMBER_OF_SELECTION_STEPS; ++cut) { cutflow[cut] = 0; singleCuts[cut] = 0; } }
Writing histograms in the destructor

Analysis::~Analysis() { testingDirectory->cd(); h_et->Write(); h_diElectronMass->Write(); h_ptRel_vs_DRmin->Write(); outputfile->Write(); outputfile->Close(); }

without the TDirectory I can save the histograms without trouble. With the histogram I get a segmentation fault. The reason being the attempt of the smart pointer to delete an already deleted pointer.

For histograms there is a SetDirectory function to disconnect these two.

I am not sure how to use the SetBit function since

did not solve the problem.

Another approach is to create the directory in memory like the histograms, however, the directory is not written:

I suppose I am missing a very small bit. Could someone please point me to it?


you are confusing yourself by introducing shared pointers here. If you would phrase your question: “How do I delete a directory that’s in a TFile? The TFile always deletes it!” you would immediately realize what the answer is :slight_smile: TFiles own their TDirectories. You shouldn’t delete them. And thus putting a TDirectory inside a smart pointer is wrong - just use a good old TDirectory*.

Cheers, Axel.

The problem was that I introduced memory leaks in the old analysis code by not taking care of pointers.
Most of these pointers were histograms owned by a TDirectory which was owned by either another directory or directly (and in the end) by a TFile.

This is why I started to introduce shared and scoped pointers and therefore became aware of the ROOT object ownership.

The ROOT ownership is a good thing to start and a confusing to end. I saw many ROOT macros which failed because of a misunderstanding of this feature (i.e. histograms loaded from a TFile and being deleted after file.Close() ). In my case I would like to be save from memory leaks and nullpointers (boost ptrs are null save, had an assertion error when I tried to access a nullpointer).

One thing I thought about is what would be if I could get a shared_ptr from TFile::mkdir:
I would be sure that the pointer is taken care of and I could still use it after a file is being closed.
But then changes wouldn’t be updated in the TFile after file.Close() which might introduce another confusion (and more problems I didn’t think about).

You guys have really a hard job.

However, as for my problem, I will try to go with shared pointers and create all histograms in memory (gROOT) and write them (and create the directories in the file) at the end of the analysis. Should work I guess.