Writing an array of objects to a tree

I am using root 4.00/08 on ubuntu/debian, gcc 3.3.5.

I am trying to write an array of events (user objects) into a tree. The code I attached is the shortest version I could come up with that reproduces the problem and has the components I need for it to suit my needs.

The thing is if I create an array of one (const Int_t NUM=1) the program runs ok. if NUM becomes larger I get a segmentation fault. I’m doing it this way, because I wanted to be able to “edit” (i.e. redo a fit, when it is needed) an event before writing it to a tree.

Another thing is that I cannot load the libEvent.so into root to start the tree viewer. The response I get is:

dlopen error: /home/andrzej/testing/./libEvtest.so: undefined symbol: _Z7fitfuncPdS_ Load Error: Failed to load Dynamic link library /home/andrzej/testing/./libEvtest.so

In the full version of the program the undefined symbol can also be the name of a static variable. Here of course, the fitting function is trivial but in the main program it’s a lot more complex. I read that the fitting function can not be a member of the class so this is what I came up with. Is there any other way to do this?

I will be grateful for any help.
Cheers,
Andrzej
array_tree.tar.gz (2.22 KB)

You forgot to implement your function Clear (declared but not implemented)
Because there is already a TObject::Clear, you should declare in Evtest.h
void Clear(Option_t *option="");
and in Evtest.C, add
void Event::Clear(Option_t *) {

}

Your tar file had one missing file EvtestLinkDef.h

Rene

sorry, I was trying to cut the code down as possible and I cut the Clear function at the last moment. I have updated the files in my first post. Sorry about that.
Andrzej

You should not allocate objects in your Event constructor.

Rene

This is due to a problem that I had in the main program. Normally I need to create a number of events corresponding to the number of files, so I had to declare an array of pointers. I had a lot of problems with memory and I found that Initializing the objects in the constructor solved them.

Removing the lines from the constructor:

 histo=new TH1F();
  func=new TF1();

in this short version doesn’t help as far as the segmentation fault and loading the library goes.
Thanks for the quick replies.
Andrzej

The fact that it even works with one is sheer luck.
You have:

char * temp=new char; sprintf(temp,"branch nr%d",i); You allocated one char for the string and are writing at least 11 characters thus writing passed the end of the allocated memory (and hence destroyed something else. You can simply use the following construct instead tree->Branch(Form("branch nr%d",i), "Event", &event[i], 32000, 99);

Cheers,
Philippe

I sincerely apologize for these bugs. They originated in the fact that I wanted to cut it down as much and as fast as possible. I should have paid more attention.

Using the suggestion with form still doesn’t solve the problem. The program crashes when NUM=2 or more. And this still doesn’t explain why the library cannot be loaded into the root command line with: .L libEvtest.so

I am including the modified source (as Philippe suggested) and the gdb back trace output:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1233718624 (LWP 10704)]
0xb75a5713 in ROOT::TF1_IsA () from /home/andrzej/cern/root/lib/libHist.so
(gdb) bt
#0  0xb75a5713 in ROOT::TF1_IsA () from /home/andrzej/cern/root/lib/libHist.so
#1  0xb7a8b788 in TClass::GetActualClass ()
   from /home/andrzej/cern/root/lib/libCore.so
#2  0xb79f5212 in TBuffer::WriteObjectAny ()
   from /home/andrzej/cern/root/lib/libCore.so
#3  0xb79f4b8b in TBuffer::WriteFastArray ()
   from /home/andrzej/cern/root/lib/libCore.so
#4  0xb7abd470 in TStreamerInfo::WriteBufferAux ()
   from /home/andrzej/cern/root/lib/libCore.so
#5  0xb7034f46 in TBranchElement::FillLeaves ()
   from /home/andrzej/cern/root/lib/libTree.so
#6  0xb702c1d1 in TBranch::Fill () from /home/andrzej/cern/root/lib/libTree.so
#7  0xb70349a5 in TBranchElement::Fill ()
   from /home/andrzej/cern/root/lib/libTree.so
#8  0xb703498c in TBranchElement::Fill ()
   from /home/andrzej/cern/root/lib/libTree.so
#9  0xb70556c3 in TTree::Fill () from /home/andrzej/cern/root/lib/libTree.so
#10 0x08048ea9 in main () at tree_test.cc:68

Thanks for the quick responses and once again sorry for making it harder.
cheers,
Andrzej
array_tree_new.tar.gz (2.17 KB)

[quote] And this still doesn’t explain why the library cannot be loaded into the root command line with: .L libEvtest.so [/quote]fitfunc is implemented in the file tree_tree.cc. This file is NOT part of your library libEvtest.so (only Evtest.C and EvtestCint.cc are) and the dictionary (EvtestCint.cc) is refering to it. To solve the problem … link your library with the missing implementation file (tree_tree.o) or move the implementation of fitfunc.

The crash itself is due to the fact that, by default, there can only be one function object with the same name. So when you execute: func = new TF1("myfunc",fitfunc,0,10,1); .... func = new TF1("myfunc",fitfunc,0,10,1);The second construction will lead to deletion of the first object. To solve your issue you can either use a different name for each function object or deregister the function from the main list (in which case you will not be able to access the function by name): Thus you would need to do something like: func = new TF1("myfunc",fitfunc,0,10,1); gROOT->GetListOfFunctions()->Remove(func);
AND change histo->Fit(func);Alternatively you could generate only ONE TF1 object, do the fit has your add it and retrieve the fitted function from the histogram (which is actually probably what you are trying to do anyway)

Cheers,
Philippe.

If I understand right this means that I can’t have the same function name (myfunc) for different objects from the array, because the above lines actually mean:

event[i]->func = new TF1("myfunc",fitfunc,0,10,1); .... event[i+1]->func = new TF1("myfunc",fitfunc,0,10,1);
Is this correct? I tried changing this in the program using Form() to change “myfunc” similar to the branch names and the program doesn’t crash. At first glance I have a small problem with reading the tree, but I will look into this.

What I’m actually trying to do is get the data from a file, fill a histogram, fit, and then maybe let the user modify the fitting function and it’s parameters and only then write the tree. That’s why the gymnastics with the array.

As far as the library thing, the solution worked. I still need to fine tune it, but the principle is there.

Thank you very much for your help and especially for your patience.
Cheers,
Andrzej