Re: Strange behaviour in TTree::TBranch split/no split

Rene Brun (Rene.Brun@cern.ch)
Mon, 25 May 1998 09:19:47 +0200


Alexander,
You have two problems in your small example:
- In your main program, you are creating TFile and TTree as objects.
When the TFile destructor is called, all associated objects in
memory are destroyed, including the TTree. The TTree object will
be deleted twice. Allways use TFile *file = new TFile
and TTree *tree = new TTree to avoid the problem. In your example,
this problem was not fatal, but it is good to remember the principle.

- The real problem is in your file test.C. You create a static
instance of a class EVENT. This cannot work. See remark at the end
of URL : http://root.cern.ch/root/HowtoReadTree.html
At each new event, TTree::GetEvent will delete the previous instance
of event and will create a new instance. This cannot work with a static
object. If you simply replace
EVENT event;
by
EVENT *event = new EVENT();
and pass the address of pointer event to SetAddress, your program
will work correctly.

Rene Brun

Alexander Zvyagin wrote:
>
> IHEP, Protvino, Russia, 24-MAY-1998
>
> Dear ROOT users!
>
> I have very simple class EVENT (see below).
> I want to store TTree of EVENTs in root
> file "test.root". Macro main.C produces file "test.root". It creates branch
> of EVENTs either in serial mode main.C(0) or in split mode main.C(1)
> Finally I have macro test.C that reads EVENTs from file "test.root".
>
> Here my four root sessions (without root startup messages).
> ----------------------------------------------------------------------
> SESSION 1 and SESSION 2: main.C and test.C in one root session
> -----------------------
> Next commands produce the same output.
> $ root -b -q main.C\(0\) test.C
> $ root -b -q main.C\(1\) test.C
> ... Skiped ...
> Processing main.C(0)... or Processing main.C(1)...
> TFile Writing Name=test.root Title=file
>
> *** Break *** segmentation violation
>
> Processing test.C...
> TFile** test.root
> TFile* test.root
> KEY: TTree EVENT tree;1 EVENT tree
> Warning: File "/users/zvyagin/PPDS/1998-05-work/TEST/./EVENT.so" already
> loaded
> 0
> 1
> 2
> 3
> NULL
>
> It's OK.
> The message "*** Break *** segmentation violation" will disappear
> if I'll use "TTree *tree = new TTree(...)" instead of "TTree tree(...)".
> (I do not worry about this message but prefer do not have it.)
> --------------------------------------------------------------------------
> SESSION 3 split mode, main.C and test.C in different root sessions
> -----------------------
> $ root -b -q main.C\(1\) ; root -b -q test.C
> ... Skiped ...
> Processing main.C(1)...
> TFile Writing Name=test.root Title=file
> ... Skipped ...
> Processing test.C...
> TFile** test.root
> TFile* test.root
> KEY: TTree EVENT tree;1 EVENT tree
> 0
> 1
> 2
> 3
> NULL
>
> It's OK.
>
> ---------------------------------------------------------------------
> SESSION 4: serial mode, main.C and test.C in different root sessions
> -----------------------
> $ root -b -q main.C\(0\) ; root -b -q test.C
> ... Skiped ...
> Processing main.C(0)...
> TFile Writing Name=test.root Title=file
> ... Skipped ...
> Processing test.C...
> TFile** test.root
> TFile* test.root
> KEY: TTree EVENT tree;1 EVENT tree
> 0
> 1
> 0
> 3
> NULL
>
> EVENTs are wrong in that case. I expect 0,1,2,3 instead of 0,1,0,3.
> Who works incorrectly: me or ROOT??
>
> Thanks in advance,
> Alexander Zvyagin.
>
> ====================================================================
> Files:
>
> EVENT.h
> --------------------------------------------------
> #ifndef EVENT___include
> #define EVENT___include
>
> #include <TObject.h>
> class EVENT : public TObject
> {
> public:
> EVENT(void) {}
> Char_t v1;
> ClassDef(EVENT,1)
> };
>
> #endif // EVENT___include
> --------------------------------------------------
>
> EVENT.c
> --------------------------------------------------
> #include "EVENT.h"
> ClassImp(EVENT)
> --------------------------------------------------
>
> main.C
> --------------------------------------------------
> int main(int split)
> {
> gSystem->Load("EVENT.so");
>
> TFile root_file( "test.root", "RECREATE", "file", 9 );
> TTree tree("EVENT tree","EVENT tree");
>
> EVENT event, *event_ptr=&event;
>
> TBranch *branch = tree.Branch("EVENT","EVENT",&event_ptr,32000,split);
> if( NULL==branch )
> {
> printf("Can not create branch.\n");
> exit(1);
> }
>
> for( int i=0; i<4; i++ )
> {
> event.v1 = i;
> tree.Fill();
> }
>
> root_file.Write();
> root_file.Close();
>
> return 0;
> }
> --------------------------------------------------
>
> test.C
> --------------------------------------------------
> void test(void)
> {
> gROOT->Reset();
>
> TFile f("test.root");
>
> gSystem->Load("EVENT.so");
>
> EVENT event, *event_ptr = &event;
>
> TTree *tree = f.Get("EVENT tree");
> if( NULL==tree )
> {
> printf("Can not find tree.\n");
> exit(1);
> }
>
> TBranch *branch = tree->GetBranch("EVENT");
> if( NULL==branch )
> {
> printf("Can not find branch.\n");
> exit(1);
> }
>
> branch->SetAddress(&event_ptr);
> Int_t nevent = tree->GetEntries();
>
> for( Int_t i=0; i<nevent; i++ )
> {
> tree->GetEvent(i);
> printf("%d\n",event.v1);
> }
> }
> --------------------------------------------------