TFile going out of scope deletes histogram

Hi,

I’m sure this has been asked many times already, however I didn’t find the answer in the forum, nor in the “Object Ownership” guide. So here we go. This code segfaults, as soon as the second function tries to draw the histogram.

[code]#include “TROOT.h”
#include “TFile.h”
#include “TH2D.h”

void openHist(TH2D* h)
{
TString fStr = “PhiCrossSectionData.root”;
TFile* fEff = new TFile(fStr);
h = (TH2D*)fEff->Get(“2DStripEffHistogram”);
h = (TH2D*)h->Clone();
h->SetDirectory(0);
}

void DebugFilescope()
{
TH2D* h;
openHist(h);
h->Draw();
}[/code]

I compile this code using .x foo.cpp+. I need this histogram in many places in my code but I don’t like the idea of having global TFiles. I thought the h->SetDirectory(0) would do the job…

What is the correct way of doing this?

  • Moritz

Do you understand what you do with: h = (TH2D*)h->Clone(); ?
Replace this statement by something like

TH2D *h2 = (TH2D*)h->Clone("h2"); and return h2 to the calling program.

Rene

Hi Rene!

Unfortunately this still doesn’t work:

[code]#include “TROOT.h”
#include “TFile.h”
#include “TH2D.h”

void openHist(TH2D* h2)
{
TString fStr = “PhiCrossSectionData.root”;
TFile* fEff = new TFile(fStr);
TH2D* h = (TH2D*)fEff->Get(“2DStripEffHistogram”);
h2 = (TH2D*)h->Clone(“h2”);
h2->SetDirectory(0);
}

void DebugFilescope()
{
TH2D* h;
openHist(h);
h->Draw();
}[/code]

What does work, however, is when I return the pointer rather than modifying the supplied pointer:

[code]TH2D* openHist()
{
TString fStr = “PhiCrossSectionData.root”;
TFile* fEff = new TFile(fStr);
TH2D* h = (TH2D*)fEff->Get(“2DStripEffHistogram”);
// TH2D* h2 = (TH2D*)h->Clone(“h2”);
// h2->SetDirectory(0);
return h;
}

void DebugFilescope()
{
TH2D* h = openHist();
h->Draw();
}[/code]

To my surprise, it even works without the cloning detour. Initially I wanted to open many files in the same function, and to return many histograms. Am I supposed to return an array of pointers in this case, rather than having given pointers filled?

Yes what you do is correct now. Your previous version was not correct C++ wise. You should have passed the pointer by reference.

Rene

Oh, so stupid… :blush: Thanks, Rene!