RE: [ROOT] Problem with TObjectTable::Delete()

From: Philippe Canal (pcanal@fnal.gov)
Date: Wed Jan 30 2002 - 21:41:19 MET


Hi Mark,

When reading back the histogram is again put back on the current directory list.
There is a simple work-around that still allow you to use the automatically
generated streamer.  Just disable the automatic generation of the streamer
function and use the following implementation:

//______________________________________________________________________________
void ClassA::Streamer(TBuffer &R__b)
{
   // Stream an object of class ClassA.

   if (R__b.IsReading()) {
      ClassA::Class()->ReadBuffer(R__b, this);
	// Detatch the histogram from the current directory.
      fHistB.SetDirectory(0);
   } else {
      ClassA::Class()->WriteBuffer(R__b, this);
   }
}

This is the same streamer implementation that would be produced by
rootcint plus one line of code.  Note that this streamer does
not depend on anything (but the fact that you have a fHistB variable)
and does NOT needed to be changed from version to version.

Cheers,
Philippe.

-----Original Message-----
From: mgb@lanl.gov [mailto:mgb@lanl.gov]On Behalf Of Mark Boulay
Sent: Wednesday, January 30, 2002 1:21 PM
To: Philippe Canal
Cc: Rene Brun; roottalk@pcroot.cern.ch
Subject: Re: [ROOT] Problem with TObjectTable::Delete()


Hello,
	I've included code for a small test class which illustrates my problem.
	Two files are included (ClassA.h and ClassA.C) which define and
implement
	ClassA, a simple class with a TH1F as a data member (fHistB).
	In CINT, I can load in the class definition (.L ClassA.C++), create
	a ClassA object and stream it to file without problem, with
	
	root [0] .L ClassA.C++
	root [1] ClassA A;
        root [2] TFile fout("test_file.root","RECREATE");
        root [3] A.Write("A");
        root [4] .q

	When I then read the object back from file, ie.

	root [0] .L ClassA.C++
	root [1] TFile fin("test_file.root","READ");
	root [2] ClassA *A = (ClassA *)fin.Get("A");

	and then quit root, I encounter the probem (segmentation violation
since
	fHistB is being deleted since there is a pointer to it in the
TObjectTable), 
	even though in the constructor for ClassA, the call is made to
fHistB.SetDirectory(0).

--Mark

Philippe Canal wrote:
> 
> Hi Mark,
> 
>       Originally, I had called B.SetDirectory(0) in
>         A's custom Streamer function, which worked, but I would prefer to use
>         the automatic Streamer.
> 
> You should probably call B.SetDirectory right after the creation of B
> (thus probably in A's constructor).
> 
> Cheers,
> Philippe.
> 
> -----Original Message-----
> From: owner-roottalk@pcroot.cern.ch
> [mailto:owner-roottalk@pcroot.cern.ch]On Behalf Of Mark Boulay
> Sent: Wednesday, January 30, 2002 12:33 PM
> To: Rene Brun
> Cc: roottalk@pcroot.cern.ch
> Subject: Re: [ROOT] Problem with TObjectTable::Delete()
> 
> Hi Rene,
>         Thanks for your reply.  Adding the call B.SetDirectory(0) in A's
> constructor
>         does not solve the problem.  Originally, I had called B.SetDirectory(0)
> in
>         A's custom Streamer function, which worked, but I would prefer to use
>         the automatic Streamer.
> 
>         Also, calling the static TH1::AddDirectory(kFALSE) works around the
>         problem, but I'd like to keep the ability to automatically add
>         histograms to the current directory.
> 
> --Mark
> 
> 
> Rene Brun wrote:
> >
> > Hi Mark,
> >
> > In the constructor of class A, you should add the following statement;
> >   B.SetDirectory(0);
> > By definition, A owns B. However the TH1F constructor (by default) will
> > add the created histogram to the list of objects in the current directory/file.
> > When the file is closed, this object is deleted. You will get the object
> > deleted twice.
> >
> > You can also turn off the feature adding automatically the histogram objects
> > to the current directory (gDirectory->GetList()) by calling the static function
> >   TH1::AddDirectory(kFALSE);
> > Note that if you do that, doing something like file->Write() will not
> > save your histograms to the file.
> >
> > Rene Brun
> >
> > Mark Boulay wrote:
> > >
> > > Hello,
> > >
> > >         I have a class (call it class A), derived from TObject which has as a
> > > data member a TH1F
> > >         (call it TH1F B).
> > >         When an object of class A is read in from file, and then the file
> > > closed,
> > >         a call is made to TObjectTable::Delete() deleting all objects which
> > > were
> > >         contained in the file.
> > >         The object A is first deleted, and then an attempt is made to delete B,
> > >         since a reference to it still exists in gObjectTable.  The problem
> > >         is that B has presumably already been deleted along with A, since it
> > >         is a data member of class A.
> > >
> > >         I'm using ROOT 3.02.07 under RH linux 7.2.
> > >
> > > Thanks in advance for assistance,
> > > Mark



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