Re: [ROOT] Content of TList stored externally in TFile

From: Rene Brun (Rene.Brun@cern.ch)
Date: Tue Aug 20 2002 - 08:57:13 MEST


Hi Christian,

As expected, setting your pointers to null in the default constructor
has solved your problem in the first job.
It is difficult to guess what could be the problem in your
second program without more info from your side.
Do you have a custom Streamer for your class? How are the pointers
initialized in this case?
Could you send the traceback from the debugger when your second job
crashes?

Rene Brun

On Tue, 20 Aug 2002, cstrato wrote:

> Dear Rene
> 
> Thank you for your tip. Sorrowly, I get a strange result, when
> setting TList of TBaseClass to null. My constructors look as follows:
> 
> //--- MyClass -----------
> class MyClass: public TNamed {
>     TFile    *fFile;     //!
>     TContent *fContent;  //!
>     TList    *fTrash;
> 
>     void AddData()    {derivedClass->AddTree();}
>     void UpdateData() {derivedClass->UpdateTree();}
>     void DeleteData() {derivedClass->DeleteTree();}
> }
> 
> MyClass::MyClass()
>           :TNamed()
> {
>     if(kCS) cout << "---MyClass::MyClass(default)------" << endl;
> 
>     fFile      = 0;
>     fContent   = 0;
>     fTrash     = 0;
> 
> cout << "TClass::IsCallingNew()= " << TClass::IsCallingNew() << endl;
> }//Constructor
> 
> MyClass::MyClass(const char *name, const char *title)
>           :TNamed(name, title)
> {
>     if(kCS) cout << "---MyClass::MyClass------" << endl;
> 
>     fFile      = 0;
>     fContent   = 0;
>     fTrash     = new TList();
> }//Constructor
> 
> //--- TBaseClass----------- (demo name of course)
> class TBaseClass: public TNamed {
>        TList  *fList;
>        TList  *fTrash;
> 
>     void AddTree();
>     void UpdateTree();
>     void DeleteTree();
> }
> 
> TBaseClass::TBaseClass()
>           :TNamed()
> {
>     if(kCS) cout << "---TBaseClass::TBaseClass(default)------" << endl;
> 
>     fList  = 0;   //<===== problem when both TList set to = 0
>     fTrash = 0;   //<===== problem when both TList set to = 0
> //   fList  = new TList();
> //   fTrash = new TList();
> 
> cout << "TClass::IsCallingNew()= " << TClass::IsCallingNew() << endl;
> }//Constructor
> 
> TBaseClass::TBaseClass(const char *name, const char *title)
>           :TNamed(name, title)
> {
>     if(kCS) cout << "---TBaseClass::TBaseClass------" << endl;
> 
>     fList  = new TList();
>     fTrash = new TList();
> }//Constructor
> 
> When I create either fList or fTrash or both in the default
> constructor, then I have the problem that the second root session
> contains the deleted objects.
> However, when I set both fList = 0 and fTrash = 0 in the default
> constructor, as you suggested, then my first root session is ok,
> and I can check the root file with TBrowser. Interestingly, in my
> second root session, where I delete trees and add new trees, I am
> no longer able to open the root file with TBrowser, instead I get
> a "*** Break *** bus error" after the output:
> root [3] TBrowser b
> root [4] ---TBaseClass::TBaseClass(default)------
> TClass::IsCallingNew()= 1
> 
> What could be the reason for this behavior?
> 
> Thank you
> Christian
> 
> 
> Rene Brun wrote:
> 
> > Hi Christian,
> > 
> > My guess is that in the default constructor for your BaseClass
> > (I hope your class is not called TBaseClass!) you set fContent
> > to a non null value.
> > The default constructor is called by ROOT I/O to create a dummy
> > instance of your class to build the class dictionary or stream in
> > an object from the file.
> > 
> > I suggest you add print statements in your BaseClass
> > constructor/destructor to see what is happening.
> > In your default constructor, you can test the return value
> > of Bool_t TClass::IsCallingNew() to find out if your constructor
> > is called by you or by ROOT I/O.
> > 
> > Rene Brun
> > 
> > 
> > On Sun, 18 Aug 2002, cstrato wrote:
> > 
> > 
> >>Dear Rooters
> >>
> >>I have a strange problem in a pretty complex program, where
> >>I store TTrees in a TFile in one root session, but am also
> >>able to add, delete or update trees in the next session.
> >>The important classes compiled as library are:
> >>class TContent: public TList {}
> >>
> >>class TBaseClass: public TNamed {
> >>    void AddTree();
> >>    void UpdateTree();
> >>    void DeleteTree();
> >>}
> >>
> >>class DerivedClass: public TBaseClass {}
> >>
> >>class MyClass: public TNamed {
> >>    TFile    *fFile;
> >>    TContent *fContent;
> >>
> >>    void AddData()    {derivedClass->AddTree();}
> >>    void UpdateData() {derivedClass->UpdateTree();}
> >>    void DeleteData() {derivedClass->DeleteTree();}
> >>}
> >>
> >>First root session:
> >>In a macro I call myClass->AddData(tree1). A tree is created in
> >>fFile, and derivedClass1 is stored in fContent.
> >>Assume that I have created three trees in this way, tree1, tree2
> >>and tree3. When I call TBrowser, everything is perfectly ok.
> >>
> >>Second root session:
> >>In a macro I call:
> >>myClass->AddData(tree4)
> >>myClass->DeleteData(tree1)
> >>myClass->DeleteData(tree2)
> >>myClass->AddData(tree5)
> >>When I open fFile with TBrowser, tree4 and tree5 are added, and
> >>their corresponding derivedClass4 and derivedClass5 is added to
> >>fContent, while tree1 and tree2 are deleted and their corresponding
> >>derivedClass1 and derivedClass2 are deleted from fContent, as
> >>expected. So far everything is ok.
> >>But now fFile contains suddenly the three derivedClass1,2,3 from
> >>the first root session as single objects in fFile. Apparently,
> >>the old content of fContent is read and stored in fFile.
> >>I do not understand, why these objects are suddenly stored in
> >>fFile, since I never call fFile->Write() but only obj->Write().
> >>
> >>The destructor of BaseClass looks as follows:
> >>BaseClass::~BaseClass
> >>{
> >>    if (fFile) {
> >>    // Write content to file only if new file or file is updated
> >>       fFile->cd();
> >>       if (fContent && (strcmp(fFile->GetOption(), "READ") != 0)) {
> >>          // kSingleKey since fContent is a TCollection!!
> >>          fContent->Write("", TObject::kSingleKey | TObject::kOverwrite);
> >>       }//if
> >>
> >>       fContent->Delete();
> >>       SafeDelete(fContent);
> >>       SafeDelete(fFile);
> >>    }//if
> >>
> >>//   fTrash->Delete();
> >>    SafeDelete(fTrash);
> >>}
> >>
> >>My questions are:
> >>Can anybody give me a hint why the objects are written to fFile?
> >>How can I prevent that the old list content is written to fFile?
> >>
> >>Thank you in advance for your help.
> >>
> >>Best regards
> >>Christian
> >>_._._._._._._._._._._._._._._._
> >>C.h.i.s.t.i.a.n S.t.r.a.t.o.w.a
> >>V.i.e.n.n.a       A.u.s.t.r.i.a
> >>_._._._._._._._._._._._._._._._
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> > 
> > 
> > 
> 
> 



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