[ROOT] Deletion of objects in class member functions

From: cstrato@EUnet.at
Date: Wed Jan 03 2001 - 20:17:03 MET


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.

2, Do I need to declare fCurFile as static?

3, Why can I not use vMatrix(x,y) when TMatrix is created on the heap?
   (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