TChain Leak: AutoDelete not propagated between files?


ROOT Version: 6.06.08
Platform: Linux
Compiler: g++ 4.9


I seem to have a memory leak issue when reading from a TChain, which manifests only after the processing proceeds to the second file. The leak relates to a TObjArray member of the top level class being leaked (not being deleted by TBranch::SetAutoDelete). Perhaps I need to do something to update the chain variables? I’m not sure what or why though.

I have a reproducer script and a couple of sample files here: https://drive.google.com/file/d/1_hHUizuoMbH9GWmOPlseABugsJDlWKw0/view?usp=sharing
I use TChain::SetBranchAddress either with a self-made object, or passing a pointer to a nullptr (both yield the same result), and call TBranch::SetAutoDelete to ensure the object gets renewed with each GetEntry call. The Event class (WCSimRootEvent) contains a TObjArray of Trigger objects (WCSimRootTrigger).
Everything appears to work fine for the first file, and after processing 500 entries in the first TFile, a gObjectTable->Print() shows there are just 3 Events and 3 Triggers in memory (as expected; there are 3 types of event in the file).
But moving onto the second TFile, it seems subsequent GetEntry calls do not delete the TObjArray member, and the application leaks memory. By the end of processing the second file, gObejctTable->Print() shows just 3 Events, but some 63 Triggers, and the application memory has been climbing linearly since moving to the second file.

Am I missing something in how I process the TChain?

I’m actually a little puzzled about the process of creating an Event for the TChain ‘to use’, given that the Event contains a TObjArray, which I believe may not be assumed to be suitable for re-use between subsequent GetEntry calls. If the TObjArray member of the Event from a previous GetEntry call is not suitable for re-use, I would assume a pre-allocated Event passed via SetBranchAddress also cannot be assumed suitable. Then, who is constructing the TObjArray member in this case, and who is responsible for deleting it?

I was able to completely plug all leaks by working with the Tree branches directly, as shown in the attached script. But it seems a little like this isn’t how TChains are supposed to be used… check_for_memory_leaks.cpp (3.8 KB)

@oshadura You seem to keep marking this as resolved; but as commented in my post, while the script attached does indeed prevent leaks,

it seems like this isn’t how TChains are supposed to be used…

i.e. @pcanal I consider this a workaround, not a solution; it would be nice to know why I cannot appear to use TChains within a normal procedure.

@marc1uk, sorry I misinterpret your post! @pcanal is on the vacation, so maybe I will try to take a look and let you know if I can help.

Oksana.

No problem, usually finding a solution is enough, i’m just the type who likes to know the why of it.
I’d appreciate any insights you can offer. :slight_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.

A ‘better’ workaround might be:

fChain->SetAutoDelete(true);

The main downside is that it implies this to all (and only those) branches for which the address is explicit set (i.e. TChain::SetBranchAddress is called)

Thanks Philippe, that works. Much neater than my hack! :+1:t2: