Re: [ROOT] TBranchElement vs TBranchObject questions

From: Rene Brun (Rene.Brun@cern.ch)
Date: Thu Jul 04 2002 - 10:52:10 MEST


Hi Corey,

On Mon, 1 Jul 2002, Corey Reed wrote:

> Hi,
>
> I have seen some unexpected behavior in a TTree that I'd like to ask
> about.
>
> The tree in question had two branches which were objects (among other
> branches of numerical types). Both objects inherit from the same parent
> class (TPhTrack), which ultimately inherits from TObject.
>
> When caling TTree->Branch([name],[class],&[pointer],32000,0) on both,
the
> first branch (a TPhMCTrack) becomes a TBranchElement, while the second
(a
> TPhSpecTrack) becomes a TBranchObject. My first question is why would
> happen. Neither object (TPhMCTrack or TPhSpecTrack) has a custom
streamer
> and both were called with splitlevel==0.
>

It is likely that your TPhSpecTrack class has a custom Streamer. In this
case, a TBranchObject is created to force a call to your custom Streamer.

> The parent class of both these objects (TPhTrack) has a TObjArray*
member,
> which owns its objects. For the objects in the TBranchObject,
> TPhSpecTrack, there was no memory leak when reading the tree with Draw()
> or GetEntry() -- the objects in the TObjArray* would get deleted or
> overwritten (I guess the latter). However, for the TBranchElement,
> TPhMCTrack, the objects in the TObjArray* would never get deleted or
> overwritten, and there was a serious memory leak. The difference in the
> way these objects are read is the difference between the default
streamer
> in TPhSpecTrack from ClassDef() and the streamer that is created by the
> TStreamerInfo / TStreamerBase for the TPhMCTrack's TBranchElement. My
> second question is why does this problem occur?

The objects in the TObjArray should be deleted. You do not mention which
version you are using. My guess is that you are using 3.02/07 or older.
Could you try with 3.03/06? 

>
> In an attempt to prevent the memory leak, I called
> TBranch::SetAutoDelete() on both branches. The TBranchObjects would get
> deleted, but the TBranchElements would not (having put a print statement
> in the destructors of both, I know this is the case). I looked through
the
> code and could not find any place where the SetAutoDelete() flag is
> checked for TBranchElements. Also, in the TStreamerInfo::ReadBuffer()
type
> that was being used (kBase), I didn't see any place where it checked the
> ok-to-delete bit of the object, but perhaps I missed it somewhere in
> TClass::ReadBuffer().
>
> Anyway, my last question is: Does TBranchElement ignore the
> SetAutoDelete() flag and if not, why were my objects in this branch not
> being deleted?


The new TBranchElement ignores SetAutoDelete. The system attempts to
reuse the existing object as much as possible with an automatic deletion
of the internal objects pointed by this object. If one of the internal
pointers point to a TObjArray that is the owner of its objects, the
objects in the TObjArray should be deleted (at least with 3.03/06).

>
> As a final note, if a use TTree::BranchOld() and call the
SetAutoDelete()
> flag, I have no memory leaks.

Is the leak coming from the objects in the TObjArray?

Rene Brun


>
> Thanks for the help!
>
>



On Mon, 1 Jul 2002, Corey Reed wrote:

> Hi,
> 
> I have seen some unexpected behavior in a TTree that I'd like to ask
> about.
> 
> The tree in question had two branches which were objects (among other
> branches of numerical types). Both objects inherit from the same parent
> class (TPhTrack), which ultimately inherits from TObject.
> 
> When caling TTree->Branch([name],[class],&[pointer],32000,0) on both, the
> first branch (a TPhMCTrack) becomes a TBranchElement, while the second (a
> TPhSpecTrack) becomes a TBranchObject. My first question is why would
> happen. Neither object (TPhMCTrack or TPhSpecTrack) has a custom streamer
> and both were called with splitlevel==0.
> 
> The parent class of both these objects (TPhTrack) has a TObjArray* member,
> which owns its objects. For the objects in the TBranchObject,
> TPhSpecTrack, there was no memory leak when reading the tree with Draw()
> or GetEntry() -- the objects in the TObjArray* would get deleted or
> overwritten (I guess the latter). However, for the TBranchElement,
> TPhMCTrack, the objects in the TObjArray* would never get deleted or
> overwritten, and there was a serious memory leak. The difference in the
> way these objects are read is the difference between the default streamer
> in TPhSpecTrack from ClassDef() and the streamer that is created by the
> TStreamerInfo / TStreamerBase for the TPhMCTrack's TBranchElement. My
> second question is why does this problem occur?
> 
> In an attempt to prevent the memory leak, I called
> TBranch::SetAutoDelete() on both branches. The TBranchObjects would get
> deleted, but the TBranchElements would not (having put a print statement
> in the destructors of both, I know this is the case). I looked through the
> code and could not find any place where the SetAutoDelete() flag is
> checked for TBranchElements. Also, in the TStreamerInfo::ReadBuffer() type
> that was being used (kBase), I didn't see any place where it checked the
> ok-to-delete bit of the object, but perhaps I missed it somewhere in
> TClass::ReadBuffer().
> 
> Anyway, my last question is: Does TBranchElement ignore the
> SetAutoDelete() flag and if not, why were my objects in this branch not
> being deleted?
> 
> As a final note, if a use TTree::BranchOld() and call the SetAutoDelete()
> flag, I have no memory leaks.
> 
> Thanks for the help!
> 
> 



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:50:58 MET