Memory leak in TTree with TList of TNamed

I might have found a bug in root, but I post here first before creating a bug report, because I cannot imagine that nobody has noticed this before. So maybe I am just doing something wrong.

If I simply read a TTree which contains a branch with a TList of TNamed, root seems to have a memory leak, even if the branch is not accessed (no branch address has been set). Here is a minimal code snippet:

[code]void memleak_test() {
TFile *fInputFile = new TFile(“test0.root”);
TTree someTree = (TTree) fInputFile->Get(“someTree”);

for(int i=0; i<someTree->GetEntries(); i++) {
  someTree->GetEntry(i);
}

}[/code]

The file “test0.root” has been generated with the following code snippet:

[code]void memleak_test0() {
TFile *fOutputFile = new TFile(“test0.root”,“RECREATE”);
fOutputFile->cd();

TTree *someTree = new TTree("someTree","a TTree");
TList* someList = new TList();
someTree->Branch("SomeList",&someList);

for(int i=0; i<100000; i++) {
  if(i%100 == 0) cout << i << endl;
  someList->Delete();
  
  for(int k=0; k<100; k++) {
    TNamed *o = new TNamed();
    someList->Add(o);
  }
  someTree->Fill();
}    
someTree->Write();

}[/code]

This also works if I compile a C++ program only using the root libraries, so it is not related to CINT. I have tested this with different root versions, mainly 5.34/01 and 5.28/00f. The behavior is always the same.

As I see little room for a mistake on my end in the reading code, maybe I have to do something differently in writing the TTree? Or is this really a bug in root which I should report in the bug tracker?

Thanks in advance for any insight!

EDIT: It also works with TObjects instead of TNamed in the TList…

Hi,

[quote] even if the branch is not accessed

someTree->GetEntry(i);[/quote]Since GetEntry is called on the TTree object all the branches that are not explicitly disabled (via SetBranchStatus) are read.

The TList is not marked as the owner (TList::SetOwner) and thus the TTree does not know, can not know that it should be deleted the object held by the TList (in you writing code, this manifest by the explicit call to someList->Delete();).

Independently, if you TList always contains the same object type, you should consider using a TClonesArray instead (which happens to also own its content by default).

Cheers,
Philippe.

Opps, I though I had checked this… Adding a “someList->SetOwner();” either at the time of writing or at reading actually resolves it!

Sorry for bothering you and thanks for your help!