TObjArray of inherited TObject as member of a class

Hello,

(Apologizing in advance for the length of what follows.)
I have a problem, that I have tried to summarize with two simple classes. One is ‘histo’ which has a TH1F as a private member, the other is ‘myarray’, which has a TObjArray as a private member. I want to store many histos in one ‘myarray’. And then put the myarray object in a tree.
I cannot access the histo.
However, if I do the same thing with a TH1F instead of a histo (i.e. put TH1Fs in a myarray), I can access the TH1F objects afterwards.
Alll code is attached in a tar file , with Makefile. The two macros are th1f.C (which works) and myhisto.C (which does not).
Any clue to what I do wrong is welcome!

The code for histo looks like:

[code]#include
#include “TObject.h”
#include “Riostream.h”
#include “TH1.h”
#ifndef histo_H
#define histo_H

class histo : public TObject{
// this is a simple wrapper for TH1F
public:

histo()
  {cout<<"building a class histo"<<endl;
  fHisto=0;
  };

~histo()
  {if (fHisto){
    delete fHisto;
    fHisto=0;
  }
  cout<<"destroying a class histo"<<endl;
  };

void SetHisto(TH1F* h)
  {
    fHisto=(TH1F*)h->Clone();

  }

TH1F* GetHisto() {return fHisto;}

private:

TH1F* fHisto;
ClassDef(histo,1);

};

#endif //histo_H
[/code]
And the code for myarray is:

[code]#include “TObject.h”
#include “histo.h”
#include “TObjectTable.h”
#ifndef myarray_H
#define myarray_H
// A simple wrapper for TObjArray…
class myarray : public TObject{
public:
myarray():fMyarray(0){
cout<<“building a class myarray”<<endl;
};

~myarray(){
  if (fMyarray){
    if (fMyarray->GetEntries()>0)
      fMyarray->Delete();
    cout<<"destroying a class myarray"<<endl;
  }
  delete fMyarray;
  fMyarray=0;
  gObjectTable->Print();
}
;

void SetANumber(TString ANumber){fANumber=ANumber;}
TString GetANumber() {return fANumber;}


void Add(TH1F *pt){
       fMyarray=new TObjArray(1);
  fMyarray->Add(pt);
}
void Add(histo *pt){
        fMyarray=new TObjArray(1);
  fMyarray->Add(pt);
}
TObjArray* GetMyarray(){return fMyarray;}

private:
TString fANumber;

TObjArray *fMyarray;
ClassDef(myarray,1);

};

#endif //myarray_H

[/code]

If I fill myarray with TH1Fs, everything is fine, I can retrieve the plots, and I can Draw() them as in the example here (called th1f.C):

[code]{
#include

gROOT->Reset();
int I =0;
int NNN=200;
gSystem->Load(“libmyarray.so”);

myarray* myarraypt=new myarray();

TTree T(“T”,“A test tree for histos”,0);
T.Branch(“event branch”,“myarray”,&myarraypt,32000,0);

while (I<NNN) {

I++;

TH1F* mine=new TH1F(“test”,“testing array class”, 10,0,10);
mine->FillRandom(“gaus”,8);

cout<<"Filling the tree "<<endl;
myarraypt->Add(mine);
T->Fill();

delete mine;
}

T->GetEntry(10);

TH1F* tempth1f= (TH1F*) myarraypt->GetMyarray()[0];
cout<Print()<<endl;
tempth1f->Draw();

}
[/code]
But If I populate the myarray with object of the class histo (macro myhisto.C) I get a segmentation fault when I plot the histogram:

[code]{
#include

gROOT->Reset();
int I =0;
int NNN=20;
gSystem->Load(“libmyarray.so”);

myarray* myarraypt=new myarray();

TTree T(“T”,“A test tree for histos”,0);
T.Branch(“event branch”,“myarray”,&myarraypt,32000,0);

histo* mine=new histo();

while (I<NNN) {

I++;

TH1F* h=new TH1F(“test”,“testing array class”, 10,0,10);
h->FillRandom(“gaus”,10);
histo* mine=new histo();
mine->SetHisto(h);

cout<<"Filling the tree "<<endl;
myarraypt->Add(mine);
T->Fill();

delete h;

}

T->GetEntry(10);
histo* temphisto= (histo*) myarraypt->GetMyarray()[0];

cout<<"Printing the histo info\n "<Print()<<endl;
TH1F* tempth1f=temphisto->GetHisto();
tempth1f->Draw();

}
[/code]
array.tar (10 KB)

Hi,

It is probably just luck that your code work with a TH1F.

You have the following:

while (I<NNN) { ... TH1F* mine=new TH1F("test","testing array class", 10,0,10); .... myarraypt->Add(mine); T->Fill(); delete mine; } In particular you do not reset the array and hence keep in it the deleted object. Hence event after event you accumulate more and more bad pointer in myarraypt.

[quote]But If I populate the myarray with object of the class histo (macro myhisto.C) [/quote]Also please note that (as you may have done already) you need to compile myhisto.C (your code will not work if it is interpreted).

Cheers,
Philippe.

Hello,

Thanks for your effort.

By ‘resetting’ the array, do you mean calling myarraypt->Clear()? Sorry my ROOT knowledge is not very deep.
(I did remove the ‘delete mine’ statement and it still works.)

I tried that to no avail.
To pinpoint the problem instead of running the macros I sent, the following lines
can be executed from ROOT:[code]
{gSystem->Load(“libmyarray.so”);

//Create a TH1F
TH1F* h=new TH1F(“test”,“testing array class”, 10,0,10);
h->FillRandom(“gaus”,10);

//Create and fill a ‘histo’ object
histo* mine=new histo();
mine->SetHisto(h);

//Create an myarray pointer and populate it
myarray* myarraypt=new myarray();
myarraypt->Add(mine);

//Now, try to retrieve the TH1F and plot it
TObjArray* oar=myarraypt->GetMyarray();
histo* oldhisto=(histo*)oar[0];
TH1F* retrieved=oldhisto->GetHisto();
retrieved->Draw();
}
[/code]
it does away with the tree filling, but still without success. I tried to run it compiled as well. Very puzzling, I cannot manage to put the finger on where the problem resides.
Cheers,
Adam

Is a C++ error.   In this case 'oar[0]' is strictly equivalent to *oar.  Hence your oldhisto pointer points to the TObjArray.  Instead use
[code]histo* oldhisto=(histo*)oar->At[0]; [/code]Cheers,
Philippe.

Is a C++ error. In this case ‘oar[0]’ is strictly equivalent to *oar. Hence your oldhisto pointer points to the TObjArray. Instead use

histo* oldhisto=(histo*)oar->At[0]; Cheers,
Philippe.

Thank you for the help. That set me on the right track and things work now!
//A