RE: i/o of objects with multiple references

From: Philippe Canal <pcanal_at_fnal.gov>
Date: Wed, 01 Feb 2006 13:22:08 -0600


Hi Sue,

Currently TClonesArray intentionally does not register to the TBuffer the addresses of its content as individual objects.

In particular this means that upon storing your std::map, the TBuffer does not know that it has already saved those objects and thus save them a 2nd time (and will restore them separately).

Changing the behavior of TClonesArray would slow down the typical case so we would prefer not to.

Also this would not prevent the same problem from re-appearing if you decided to split your object so that the TClonesArray and the map are in 2 different branches.

In addition, we currently have no means for the user to indicate whether an STL collection containing pointers own or does not own the objects pointed to. So for now, we assume (to avoid memory leaks) that they do own it. This assumptions is used only in the I/O code and has any effect only if the user does not explicitly clear the collection before or after reading an entry in a TTree (So for example via TTree::Draw).

So for theses reasons I recommend a slight modification of your implementation where instead of having a direct link between the pointer and the weight, you make it indirect.

For example you could use a map<int,float> where the int is an index (or uniqueId) representing the Hit (for example this number could be the index of the Hit in the TClonesArray).

Cheers,
Philippe

-----Original Message-----
From: owner-roottalk_at_pcroot.cern.ch [mailto:owner-roottalk_at_pcroot.cern.ch] On Behalf Of Sue Kasahara
Sent: Sunday, January 29, 2006 4:03 PM
To: roottalk_at_pcroot.cern.ch
Subject: [ROOT] i/o of objects with multiple references

Hi roottalk,
I have an example of a data structure that doesn't behave the way I would expect it to behave on i/o, and I'm wondering if you can help me understand what should be done. One of our record types has an odd structure due to historical reasons, so I apologize in advance for what I'm about to show you. A simplified version of this record (SimRecord) is in the tar file, and it has:
  A TObjArray containing:

     i)a TClonesArray of Hit's.
    ii)a Signal object which has a std::map<const Hit*, Float_t weight>

       data member containing a list of Hit ptrs which are a subset of those
       contained in the TClonesArray.

The Signal does not have ownership of the Hit's, which are all owned by the TClonesArray.
The entire TObjArray is written out to one branch of a root TTree. I find that on input, the range of Hit ptr addresses in the Signal map do not match those stored in the TClonesArray, indicating that multiple referencing to individual Hit objects were not reconstructed properly on input. This causes
a memory leak on input.
  This is not the behavior that I would expect given that both the TClonesArray
and Signal object were written out to the same TObjArray data branch.   Is there a reason for this, and is there a way to properly input the data while
avoiding a memory leak, given that we already have a large number of files with
data stored in this format?
The tar file contains a script testwrt.C to create a small data file, and testrd.C
to read the file, to illustrate the problem. I am using root development, dated Jan. 22, 2006, on linux. Thanks for your help in advance.
Regards,
-Sue Received on Wed Feb 01 2006 - 20:34:10 MET

This archive was generated by hypermail 2.2.0 : Mon Jan 01 2007 - 16:31:57 MET