Deleting ROOT objects causes crash

I’m attempting to be a good steward of the pointers I make in my C++ code; however, I’m having difficulty cleaning up the ROOT objects without crashes.

I’ve found several topics on this in the forums:

I’ve also read through the documentation on ownership of pointers in root at root.cern.ch/root/htmldoc/guide … rship.html

In my code I instantiate new ROOT objects on my own, without reading from a file or being the return of another call. For example: new TH1F(“name”, “title”, bins…)

I believe from the forum topics and ownership documentation that in this case I should be responsible for calling the ‘delete’ on these objects, but that is crashing my application.

Setting the kCanDelete and kMustCleanup bits doesn’t change the behavior. Incidentally, if I try to call TH1::SetDirectory(0), TH1::Reset(), or TH1::Delete() it also crashes in a manner similar to the ‘delete’ call. I’ve not been able to learn if this is related to my issue. I’ve also tried calling TH1::AddDirectory(kFALSE) before instantiating any new objects, but that doesn’t prevent crashes either. I initially suspected that something else is deleting my instances, so I was trying the various methods above to prevent that by trying to declare my code as the owner.

Any pointers (pun intended) on where I could look?

Thanks!

Hello,
I’ts hard to answer without code that represents this issue, for example this:

#include <TH1D.h>
void test(){
	TH1D *hh = new TH1D("a","b",100,0,1);
	hh->Fill(2.0);
	delete hh;
}

Works fine.

Perhaps you have used a TFile which has taken ownership of the objects?

#include <TFile.h>
#include <TH1D.h>
void test(){
   TFile *f = new TFile("test.root","CREATE");
   TH1D *hh = new TH1D("a","b",100,0,1);
   hh->Fill(2.0);
   f->Write();
   f->Close();
   //Do not delete hh as f has ownership.
   //delete hh;
   delete f;
}

Unfortunately my code isn’t simple enough to paste in as a snippet in a forum. I will try to work up a simpler example that still causes the problem.

I do read histograms from files, but the TH1 and TF1 I’m having problems deleting right now weren’t read from or written to files, so I don’t believe that the TFile holds ownership of the pointer. I did read in the documentation where TFile will manage the lifecycle of pointers associated with it though. I’ll take another look to be sure I’m not missing something with these objects getting written to files I wasn’t expecting. I know they aren’t read from the files as I do a ‘new’ call to create them.

Note that the “hh” (“a”) histogram in ksmith’s example was NOT retrieved from the “f” file. It was NEWLY created (in a way that it became “connected” to the “f” file).
If you wanted to “disconnect” it from “f”, you would need to:
hh->SetDirectory(0); // (0) … or … (gROOT)

I’ve tried the SetDirectory(0) call unsuccessfully, too. In my original question, you’ll see where I noted calling that function (among others documented to let one manage ROOT pointers) actually causes a similar crash. I suspect this means that ROOT is trying to manage the TH1 and TF1 pointers for me somewhere else, but I’ve yet to figure out where that might be.

Is your program multithreaded, and is “Root.ObjectStat: 1” in your .rootrc file? This line enables some very thread unsafe code that happens in the constructor and destructor of every TObject, which could be causing your issue.

If the aim is to write an object to the file and then freeing the memory, functions would help.

Inside the main program, we open the file with “RECREATE” tag so that any previous file gets overwritten, then we just close it. Later we will update this file inside a function.

void writeObject(TString file_path, TH1D *hist);

int main(){
  TFile file("filepath/filename.root","RECREATE");
  file.Close();
   
  TH1D *hh = new TH1D("a","b",100,0,1); //ksmith's example 
  hh->Fill(2.0);
  writeObject("filepath/filename.root", hh);
  delete hh;

  
  return 0;
}


void writeObject(TString file_path, TH1D *hist){

  TFile f(file_path,"UPDATE");
  f.cd(); 
  hist->Write();
  f.Write();
  f.Close();
  return;
}

This way the histogram inside the main doesn’t belong to any files and hence can be deleted.