TTree->Show()

Dear Rooters,

Using the Show() method in TTree I obtain a “bus error”.

ROOT 5.22/00a (tags/v5-22-00a@27441, May 08 2009, 13:15:54 on macosx 10.4.11)
gcc version 4.0.1 (Apple Computer, Inc. build 5363)

I have a class (SamplePoint) inheriting from TObject containing only one Short_t so that a TClonesArray of type Short_t can be contained in another class (Signal).
(I had problems reading std vectors from a Tree and also memory leaks
with Int_t fNSamples; // # of sampled points
Short_t *thisSample; //[fNSamples]
contained within another class, so I went down the TClonesArray of Short_ts path)

If in a macro I do a simple
{
TFile *f = TFile::Open(“TestEvent.root”);

TTree testT = (TTree) f->Get(“testTree1”);

for(Int_t i = 0; i < 3; i++) {
testT->Show(i);
}
}

I get the obvious warnings :

Warning in TClass::TClass: no dictionary for class Signal is available
Warning in TClass::TClass: no dictionary for class SamplePoint is available

But, the N Short_t of the TClonesArray values are displayed.

However, when I try and read in the dictionary via gSystem->Load("./libTNT2Event.so");, or,
gROOT->ProcessLine(".L TNT2Event.cxx++"); then I get a bus error.

Included is a tar of the reduced problem.
sequence :

make TestEvent
./TestEvent
root -l CheckTree.C

within CheckTree.C are the readDict and showBusError flags to switch behaviour.

Probably related is the fact that when I try and read the size of the TClonesArray using

Signal *signal = new Signal();

TClonesArray *samplePoints = new TClonesArray();
samplePoints = signal->GetSamples();
Int_t nSamples = samplePoints->GetLast() + 1;

nSamples is always 0.

Many thanks,
Karl Hauschild
test5.tar.gz (78.5 KB)

Philippe will look at your problem once he will be back.

Rene

Hi,

The problems comes from the Signal destructor functions in your code that deletes the TClonesArray that is referred to by the static/global variable fgSamples but does not update that pointer … hence leading to the reuse of the ‘deleted’ TClonesArray. Use:Signal::~Signal() { Clear(); if(fSamples) { if (fSamples == fgSamples) { fgSamples = 0; } delete fSamples; } }or do not delete the TClonesArray or do no use a ‘static’ TClonesArray.

Cheers,
Philippe.

Hi and thanks for the help,

I followed the code change advice. Now I do get the correct number of
sample points stored in the TClonesArray. However, when I try and use
TTree->Show() I have a bus error.

(NB I used a static TClonesArray as the signal class is a member of
another class and I found, probably a fudge, that using static solved a memory leak problem)

In the previously included CheckTree.C macro I test the following cases :

Int_t readDict = 0; //Do not read in dictionary

and get the expected :

root [0]
Processing CheckTree.C…
Warning in TClass::TClass: no dictionary for class Signal is available
Warning in TClass::TClass: no dictionary for class SamplePoint is available

and testT-Show(3) gives :

======> EVENT:2
OscBranch = (Signal*)0x329dc40
fTriggerCounter = 2
fNSamples = 2000
fSamples = 2000
fSamples.fPoint = 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22

Int_t readDict = 1; //Read in the dict
Int_t showBusErorr = 0; //do not use TTree->Show()

I can get access the the class members I want and the number of samples is correctly obtained this time.

But when I try and combine 1 and 2 :
3)
Int_t readDict = 1; //Read in the dict
Int_t showBusErorr = 1; //try and use TTree->Show()

TTree->Show(i) works correctly, but now, the code in case 2 causes
a bus error when I try and use TTree->GetEntry()

Best regards
Karl

Hi,

The problem is still the static TClonesArray. Now you have 2 Signal objects are both pointing at the same TClonesArray[code]testT->Show(i); // Creation of a Signal object (let’s call it ‘SigOne’)

Signal *signal = new Signal(); // Creation of second Signal object (let’s call it SigTwo) which is connected with the same TClonesArray.

bSignals->SetAddress(&signal); // Induce the deletion of SigOne (no longer needed) which induce the deletion of the TClonesArray (which SigTwo still points to).


testT->GetEntry(i); // Using SigTwo and the deleted TClonesArray …
[/code]

Conclusion, the ~Signal destructor can not delete the static TClonesArray. (i.e. do no use a static TClonesArray and/or never delete it).

Cheers,
Philippe.

Sorry about the delay between posts [no longer fresh in the mind].

I now wish to add my previous two classes into an “event” class so that :

the event class [OscillogramEvt] contains a TClonesArray of Signal classes
and each Signal contains a TClonesArray of SamplePoints. In this simplified example the OscillogramEvt also contains a time-stamp field.

The small test code TestEvent.cxx illustrates the memory leak I have when I try to add a “Signal” to the OscillogramEvt.

Please could someone help me understand my mistake.

Thanks,
Karl Hauschild
test5b.tar.gz (6.63 KB)