My Pointer to Container (TClonesArray) example not working

Hi Rooters,

a little while ago Konstantin was asking how a class that is stored in a container (ie. TClonesArray) can get information about the “Parent” class.
http://root.cern.ch/phpBB2/viewtopic.php?t=7438

Philippe suggested, that one has to store a pointer to the parent class in the class that is put into the container.
Please find attached a small example of such a setup. There are two classes A and B. A contains a TClonesArray of B’s. B contains a pointer to the parent A.
Both are saved into a tree. While trying to read this back from the tree, the wrong address to A is set in B. What is wrong with my implementation?

To Run the example please use.L testTClonesArray.c+ testTClonesArray()

here is the output, that I get:Creating 2 A's A(0331FF98) contains 9 B's B(1) belongs to 0331FF98 B(2) belongs to 0331FF98 B(3) belongs to 0331FF98 B(4) belongs to 0331FF98 B(5) belongs to 0331FF98 B(6) belongs to 0331FF98 B(7) belongs to 0331FF98 B(8) belongs to 0331FF98 B(9) belongs to 0331FF98 A(0331FF98) contains 7 B's B(1) belongs to 0331FF98 B(2) belongs to 0331FF98 B(3) belongs to 0331FF98 B(4) belongs to 0331FF98 B(5) belongs to 0331FF98 B(6) belongs to 0331FF98 B(7) belongs to 0331FF98 reading root file The tree has 2 A's reading 1 A(032FD9D8) contains 9 B's B(1) belongs to 031B1698 B(2) belongs to 031B1698 B(3) belongs to 031B1698 B(4) belongs to 031B1698 B(5) belongs to 031B1698 B(6) belongs to 031B1698 B(7) belongs to 031B1698 B(8) belongs to 031B1698 B(9) belongs to 031B1698 reading 2 Error: C++ exception caught (tmpfile)(1) (void)0 *** Interpreter error recovered ***

I’m using the recommended version of ROOT (Ver. 5.20) on Windows XP.

Thank you,
Lutz
testTClonesArray.c (2.7 KB)

You must implement a valid destructor for your class A, or alternatively add the statement

delete a; a=0; after draw(a) in ReadRootFile.

Note that the way you use the TClonesArray is not efficient.
a TClonesArray should be created once and the elements overwritten at each entry.

Rene[/code]

Hi Rene,

[quote]Note that the way you use the TClonesArray is not efficient.
a TClonesArray should be created once and the elements overwritten at each entry. [/quote]

Hmm, but this is exactly what I wanted. In class A should be a container that allocates Memory only once and then reuses this space whenever needed. That’s why I don’t delete class A after every draw. I thought that the container is just cleared and the placement new only allocates new memory when there is not enough already allocated.

As you can see from the output that I posted in my first post, when reading the tree, already reading the first “A” from the tree B’s pointer to the containing A is wrong. If I understand right, this might be due to a missing destructor. Could you help me with this?
I have tried the following~A() {fB.Delete();} or ~A() {fB.Clear("C");}
Both options didn’t solve the problem. Adding a delete a; a=0;
worked, but then I have the scenario, that for every iteration the old memory will be freed and new memory has to be allocated. Which is not what I want.

Thank you,
Lutz

Hi Lutz,

To solve your problem, simply use the following line to declare in B A *pA; //! pA is a pointer to this object's container and is set by the constructor and hence does not need to be stored in the file.The //! tells the I/O that pA should not be stored in the file (without it, not only pA is stored in the file but when restoring it, the previous value is ‘deleted’ … hence destroying the object A that is actually being used – i.e. without the //! or a //-> the I/O thinks that the B object owns the value being pointed to by pA).

Cheers,
Philippe.