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

From: cstrato (cstrato@aon.at)
Date: Wed Aug 21 2002 - 20:55:23 MEST


Dear Rene

Thank you for your reply.
While reducing my program to the bare bones, I could meanwhile
find my mistake. In update mode I called:
    fContent = (XContent*)(fFile->Get(kContent));
    fContent->Write();
Writing fContent caused my troubles.

Best regards
Christian


Rene Brun wrote:

> 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