[ROOT] Re: Deletion of objects in class member functions

From: Rene Brun (Rene.Brun@cern.ch)
Date: Wed Jan 03 2001 - 22:24:51 MET


Hi Christian,

On Wed, 3 Jan 2001 cstrato@EUnet.at wrote:

> Dear Rene
> 
> Thank you very much for answering my questions and showing me the problems
> in my code, i.e. that vData of struct DATA has to be global.
> (http://root.cern.ch/root/roottalk/roottalk01/0000.html)
> 
> My goal is to implement the functions fillarray() and readarry() as member
> functions of class MyClass which I want to use as library "libMyClass" in the
> macro "Macro.C" shown below. Furthermore, I want to clone "vClassATree"to
> "vDataTree", where I want to add a new branch and store this tree in a new
> file (vDataFile)."vMyClass->Fill()" does already seem to work as expected,
> but "vMyClass->Read()" results in a segmentation violation.
> 
> I have the following questions:
> 
> 1, A couple of objects are created in the member functions: TFile, TTree, TBranch.
>    When and how do I have to delete these objects? This is not quit clear to me.
> 

You seem to use a complex logic for a simple problem. Anyhow, if you
activate
  delete fCurFile;
in your class destructor, the TFile and TTree object created in the Fill 
function will be deleted by the destructor.

> 2, Do I need to declare fCurFile as static?

NO

> 
> 3, Why can I not use vMatrix(x,y) when TMatrix is created on the heap?


I do not understand this point without having a working example.


Rene Brun

>    (when
used in a macro in a normal function it is possible)
>    I get the following error when compiling libMyClass:
> [christian@cookiebook rootcode]$ gmake -f Makefile4MyClass
> g++ -O -Wall -fPIC -fsigned-char -I/usr/X11/include -I/opt/root/include -c MyClass.cxx
> 
> MyClass.cxx: In method `void MyClass::Fill(const char *, int)':
> MyClass.cxx:143: `vMatrix' cannot be used as a function
> 
> Thank you once again for your help.
> 
> Best regards
> Christian Stratowa
> Vienna, Austria
> 
> 
> /******************************************************************************
> * Macro.C                                                                     *
> ******************************************************************************/
> {
>    gROOT->Reset();
>    gSystem->Load("/opt/rootcode/libMyClass.so");
> 
>    MyClass *vMyClass = new MyClass("Test","Title","/opt/rootdata/DataFile.root",
>                                    "/opt/rootdata/FileA.root");
> 
> // clone tree from FileIn to FileOut and add new branch with text.txt
>    vMyClass->Fill("/opt/rootdata/text.txt");
> 
> // read tree from FileOut and print data
>    vMyClass->Read(0);
> 
> // cleanup
>    delete vMyClass;
> }//macro
> 
> 
> /******************************************************************************
> * MyClass.h                                                                   *
> ******************************************************************************/
> #ifndef __MyClass__
> #define __MyClass__
> 
> #include etc
> 
> typedef struct {
>    Float_t Meas;
>    Int_t x,y;
> } DATA;
> 
>   DATA vData;   //=====> should vData be declared static?
> 
> class MyClass: public TNamed {
>    private:
>       TString         fDataFileName;
>       TFile          *fClassAFile;
>       TFile          *fCurFile;
> 
>    public :
>       MyClass(){}
>       MyClass(const char *vName,const char *vTitle,
>                const char *vDataFileName,const char *vClassAFileName);
>       ~MyClass();
>       void Fill(const char *vText);
>       void Read(Int_t vNum);
> 
>       ClassDef(MyClass,1) //MyClass
> };
> 
> class ClassA: public TObject {
>    private:
>       variables
>    public :
>       ClassA(){}
>       ~ClassA(){}
>       Set, Get functions
> 
>       ClassDef(ClassA,1) //ClassA
> };
> 
> #endif
> 
> 
> /******************************************************************************
> * MyClass.cxx                                                                 *
> ******************************************************************************/
> #include etc
> #include "MyClass.h"
> 
> ClassImp(MyClass);
> ClassImp(ClassA);
> 
> //----------------------------------------------------------------------//
> MyClass::MyClass(const char *vName,const char *vTitle,
>           const char *vDataFileName,const char *vClassAFileName): TNamed(vName,vTitle)
> 
> {
>    fDataFileName = vDataFileName;
>    fClassAFile = 0;
>    fCurFile = 0;
> 
>    TFile *vClassAFile = new TFile(vClassAFileName,"READ");
>    if (vClassAFile->IsOpen()) {
>       fClassAFile = vClassAFile;
>    } else {
>       exit(1);
>    }//if
> }//Constructor
> 
> //----------------------------------------------------------------------//
> MyClass::~MyClass()
> {
>    delete fClassAFile;  //====>correct? or clone of vClassAFile?
> //   delete fCurFile;     //====>??
>    fCurFile = 0;
> }//Destructor
> 
> //----------------------------------------------------------------------//
> void MyClass::Fill(const char *vText)
> {
> //   TMatrix *vMatrix = new TMatrix(vNRows,vNCols);
>    TMatrix vMatrix(vNRows,vNCols);
> 
>    char vHeader[255];
> 
>    ifstream vInput(vText, ios::in);
> 
>    while (1) {
>       vInput.getline(vHeader,255);
>       vName = &vHeader[0];
> 
>       if (!vInput.good()) {
>          break;
>       }//if
> 
>    }//while
> 
> // clone ClassAtree to copy ClassA to datatree
>    TTree *vClassATree = (TTree*)fClassAFile->Get("vTree");
>    ClassA *vClassA = new ClassA();
>    vClassATree->SetBranchAddress("vClassA",&vClassA);
> 
>    TFile *vDataFile;
>    if (gSystem->AccessPathName(fDataFileName)) {
>       vDataFile = new TFile(fDataFileName,"CREATE");
>    } else {
>       vDataFile = new TFile(fDataFileName,"UPDATE");
>    }//if
> 
>    if (vDataFile->IsOpen()) {
>       fCurFile = vDataFile;  //===> should fCurFile be static?
>    } else {
>       exit(1);
>    }//if
> 
>    TTree *vDataTree = vClassATree->CloneTree();
> 
>    TString vBranchName = "vDataBranch";
> //   DATA vData;
>    TBranch *vDataBranch = vDataTree->Branch(vBranchName,&vData,"Meas/F:x/I:y");
> 
> // fill databranch
>    Int_t nentries = (Int_t)(vClassATree->GetEntries());
> //   Int_t nentries = (Int_t)(vDataTree->GetEntries());
>    for (i=0;i<nentries;i++) {
> //      vSCTree->GetEntry(i);
>       vDataTree->GetEntry(i);
> 
>       vInput >> x >> y >> Meas;
>       vData.Meas = Meas;
>       vData.x = x;
>       vData.y = y;
>       vMatrix(x,y) = Meas;  //====> error when vMatrix = new TMatrix();
> 
>       vDataBranch->Fill(); // code is incomplete, vMatrix is not stored
>    }//for
> 
>    vInput.close();
> 
>    vDataFile->Write();
> 
>    delete vClassA;
> }//Fill
> 
> //----------------------------------------------------------------------//
> void MyClass::Read(Int_t vNum)
> {
>    ClassA *vClassA;
> //   DATA vData;
> 
>    TFile *vFile = new TFile(fDataFileName);
>    TTree *vTree = (TTree*)vFile->Get("vTree");
>    vTree->SetBranchAddress("vClassA",&vClassA);
>    vTree->SetBranchAddress("vDataBranch",&vData);
> 
>    Int_t nentries = (Int_t)(vTree->GetEntries());
>    for (Int_t i=0;i<nentries;i++) {
>       vTree->GetEntry(i);
>       vX = vData.x;
>       vY = vData.y;
>       vMeas = vData.Meas;
>       printf("x=%8i,y=%8i,meas=%8f\n",vX,vY,vMeas);
>    }//for
> }//Read
> 
> 
> 
> Rene Brun wrote:
> 
> > Hi Christian,
> >
> > 2- Why your program crashes ?
> >    ==========================
> >  You have a scope problem. In your function readarray, you set the
> > branch address to a local struct. When you leave the scope of this
> > function,
> > this address becomes invalid. The browser reads at this invalid address.
> > One simple solution is to declare your struct in the global scope as shown
> > in the modified example below.
> >
> > Rene Brun
> >
> 



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:33 MET