Getting the instance of an event class by a static method

Dear ROOT developers and users,

I am using ROOT ver4.04 on Linux 2.4.31.
I am in a trouble with writing a user-defined object as a branch of a Tree object.
I added a static data member that points the instance of the object (i.e. ‘this’ pointer) and a static function that returns the pointer
in order to access the object in different functions.
I attached a simple program.
This example runs fine, but, the problem is, putting this in more complicated program(actually Geant4) causes a crash at FillTree()
in spite of exactly the same definition of the event class.
Use of a global pointer instead of the static method eliminates the crash.

Could some one give me an idea on where to check to solve the problem ?

Kame

backtrace:

#0  0x41e6dc11 in kill () from /lib/i686/libc.so.6
#1  0x41dfd341 in pthread_kill () from /lib/i686/libpthread.so.0
#2  0x41dfd6bb in raise () from /lib/i686/libpthread.so.0
#3  0x41e6d8a4 in raise () from /lib/i686/libc.so.6
#4  0x41e6f008 in abort () from /lib/i686/libc.so.6
#5  0x4069cc15 in TUnixSystem::Abort(int) () from /opt/root/4.04/lib/libCore.so
#6  0x406a12e3 in TUnixSystem::DispatchSignals(ESignals) ()
   from /opt/root/4.04/lib/libCore.so
#7  0x406a13c9 in SigHandler(ESignals) () from /opt/root/4.04/lib/libCore.so
#8  0x4069d986 in sighandler(int) () from /opt/root/4.04/lib/libCore.so
#9  0x41dffe8e in __pthread_clock_settime () from /lib/i686/libpthread.so.0
#10 0x41e6d908 in killpg () from /lib/i686/libc.so.6
#11 0x41408725 in TBranchElement::FillLeaves(TBuffer&) ()
   from /opt/root/4.04/lib/libTree.so
#12 0x413fcf17 in TBranch::Fill() () from /opt/root/4.04/lib/libTree.so
#13 0x41407acc in TBranchElement::Fill() () from /opt/root/4.04/lib/libTree.so
#14 0x41407a3d in TBranchElement::Fill() () from /opt/root/4.04/lib/libTree.so
#15 0x41430e11 in TTree::Fill() () from /opt/root/4.04/lib/libTree.so
#16 0x080f64ea in MyEventAction::EndOfEventAction(G4Event const*) ()
    at G4VTouchable.icc:86
#17 0x08259043 in G4EventManager::DoProcessing(G4Event*) ()
#18 0x0823c838 in G4RunManager::DoEventLoop(int, char const*, int) ()
#19 0x0823a95d in G4RunManager::BeamOn(int, char const*, int) ()
#20 0x082414fb in G4RunMessenger::SetNewValue(G4UIcommand*, G4String) ()
#21 0x0843786f in G4UIcommand::DoIt(G4String) ()
#22 0x0843de95 in G4UImanager::ApplyCommand(char const*) ()
#23 0x081ca91c in G4UIterminal::ExecuteCommand(G4String) ()
    at G4VTouchable.icc:86
#24 0x081cbc6a in G4UIterminal::SessionStart() () at G4VTouchable.icc:86
#25 0x080f4513 in MyApplication::StartSession() ()
#26 0x080f38aa in main ()
#27 0x41e5ac1f in __libc_start_main () from /lib/i686/libc.so.6

test.tar.gz (1.34 KB)

When you do: Event *e = new Event(true); t->Branch("test_branch", &e);the tree record the address of the pointers and not the address of the object.
If you have to use the structure you have (which is very inefficient) you should use a FillTree function more like:

inline void FillTree(const char *name, Event *e); { if (TTree *t = dynamic_cast<TTree *> (gFile->Get(name))) { t->SetBranchAddress("test_branch", &e); t->Fill(); t->ResetBranchAddresses(); } }
Cheers,
Philippe.

Hello Philippe,
thank you for the reply.

[quote=“pcanal”]When you do: Event *e = new Event(true); t->Branch("test_branch", &e);the tree record the address of the pointers and not the address of the object.
[/quote]

So, not only the event object but also the address of the pointer pointing the event object must be persistent?

The program works fine with this code. Thanks a lot.
Which do you mean is inefficient using dynamic_cast or setting the branch address every time the tree is filled?

Kame

[quote]So, not only the event object but also the address of the pointer pointing the event object must be persistent? [/quote]Indeed.

[quote]gFile->Get(name)))
t->SetBranchAddress(“test_branch”, &e);
t->ResetBranchAddresses(); [/quote]are 3 operation that you do not have to redo each time (if you structure you soft just so). (and they are relatively slow operation (SetBranchAddress was greatly improved in ROOT 5))

Cheers,
Philippe

I realized that the persistent pointer for the event obejct already exists as a member of the class, and
I only need to make sure the address of this pointer is passed to TTree::Branch() function.

I provided a method like

Event **Event::GetAddressPtr() { return &theInstance; }

and replaced

Event *e = new Event(true);
t->Branch("test_branch", &e)

with

Event *e = new Event(true);
t->Branch("test_branch", e->GetAddressPtr());

I guess this is one of the simplest solution for this issue,
although the overhead of gFile->Get(name) may still matter.
But anyway, we need to use a kind of container which objects are stored in or retrieved from in order to book or fill Trees or histograms in separate functions, which is quite a common case, I guess.

Kame