Re: [ROOT] No AutoDelete ot TClonesArray in TreeViewer?

From: Daniel Cussol (cussol@in2p3.fr)
Date: Fri Oct 25 2002 - 12:10:13 MEST


Hi Rene,

> 
> - if calling TClonesArray::Delete instead of Clear solves your leak
> problem, this means that your Fragment class is allocating objects or
> arrays dynamically. If you want to take advantage of the TClonesArray
> you should avoid this as much as possible.
> Note also that 3.03/09 takes care of this problem.
> 

My Fragment class is very simple. I have joint as attached files the
sources of the Event and Fragment classes. In my interactive ROOT session,
I load the libraries by using ACliC (.L Fragment.C+ and .L Event.C+). I do
not see where the memory is allocated dynamically in the Fragment class. 
Is it when I use the TVector3 object? I have replaced the TVector3 by 3
doubles in a test, but nothing changes: I still have a memory leak when I
use the TTreeViewer or if I call TClonesArray::Clear() instead of
TClonesArray::Delete() in my TSelector. Is there a way to access the
number of TVector3 objects in the heap? I have tried tu use the
TObjectTable, but I did not manage to access the informations concerning a
particular class. Could it be possible to have a mthod like
TObjectTable::Print("TVector3") where only the informations for the
TVector3 class is displayed?
 Thanks for your answers
 Friendly


Daniel CUSSOL

LPC Caen
Boulevard du Marechal Juin
14050 CAEN CEDEX

e-mail : cussol@in2p3.fr
Tel    : +33-(0)2-31-45-29-73
FAX    : +33-(0)2-31-45-25-49


//
// D.Cussol 
//
// 3/11/2000:
// Creation d'une classe relative aux clusters generes par les calculs 
// N Corps
//

#ifndef Fragment_h
#define Fragment_h 
#include <iostream.h>
#ifndef ROOT_TNamed
#include "TNamed.h"
#endif
#ifndef ROOT_TVector3
#include "TVector3.h"
#endif


//class Fragment:public TNamed
class Fragment:public TObject
	{
// Champs Statiques
// Vecteurs contenant les valeurs des energies, des rayons, etc. en fonction de
// la taille
        public:
        static  int     nb;
        static  int     nb_crea;
        static  int     nb_dest;
        static  double  mnuc;

// Champs non statiques
	
	public:
		int		A;		// nombre de nucleons
		int		Z;		// nombre de charges
		TVector3	v;		// vitesse

// Methodes
	public:
	void init_Fragment(void);

	public:
	Fragment(void);				// constructeur par defaut
	
	virtual ~Fragment(void);		// destructeur
	
	
//      Methodes d'acces direct aux champs
	virtual void Set(int A, int Z,TVector3 v);
	virtual int	Get_A(void); 	
	virtual int	Get_Z(void); 	
	virtual TVector3 Get_Vit(void);
	virtual void   Set_A(int a); 	
	virtual void   Set_Z(int z); 	
	virtual void   Set_Vit(TVector3 v);
	virtual void   Set_Vit(double vx, double vy, double vz);

//      Methodes d'acces calculees
	virtual void   Set_Energie(double e);
	virtual void   Set_Theta(double theta);
	virtual void   Set_Phi(double phi);
	virtual double Get_Masse(void);
	virtual double Get_Theta(void);
	virtual double Get_Phi(void);
	virtual double Get_Ecin(void);
	virtual double Get_Eperp(void);
	virtual double Get_Rayon(void);
	virtual double Get_Egoutliq(void);
	
	virtual void Affiche(void);

	ClassDef(Fragment,1)
	
	};
#endif

//
// D.Cussol 
//
// 21/10/2002:
// Creation d'une classe relative aux fragments INDRA 
// Formation ROOT
//

#include <math.h>
#include <stdio.h>
#include "Fragment.h"
#include "TMath.h"

ClassImp(Fragment)

int	Fragment::nb=0;
int	Fragment::nb_crea=0;
int	Fragment::nb_dest=0;
double	Fragment::mnuc=931.5;

//============================================================================
// Methodes de base
//============================================================================
//
// Initialisation des champs de Fragment
// Cette methode privee n'est appelee par les createurs
//
void Fragment::init_Fragment(void)
	{
        nb++;
	Z=0;
	A=0;
	v.SetXYZ(0.,0.,1.);

	nb_crea++;
	}

//
// Createur par default
//
Fragment::Fragment(void):TObject()
	{
	init_Fragment();
	}
	
// 
// Destructeur
//
Fragment::~Fragment(void)
       {
        nb--;
	nb_dest++;
       }
//============================================================================
// Acces directs aux champs
//============================================================================
//
// Methode d'attribution de valeur des champs
//
void Fragment::Set(int aa, int zz, TVector3 vit)
	{
	A=aa;
	Z=zz;
	v=vit;
	}
//
// Methode d'attribution de A
//
void Fragment::Set_A(int aa)
	{
	A=aa;
	}
//
// Methode d'attribution de Z
//
void Fragment::Set_Z(int zz)
	{
	Z=zz;
	}
//
// Methode d'attribution de la vitesse
//
void Fragment::Set_Vit(TVector3 vit)
	{
	v=vit;
	}
//
// Methode d'attribution de la vitesse
//
void Fragment::Set_Vit(double vx, double vy, double vz)
	{
	v.SetXYZ(vx,vy,vz);
	}
//
// Nombre de particules
//
int Fragment::Get_A(void)
	{
	return A;
	}
//
// Nombre de charges
//
int Fragment::Get_Z(void)
	{
	return Z;
	}
//
// vitesse
//	
TVector3 Fragment::Get_Vit(void)
	{
	return v;
	}

//============================================================================
// Acces calcules aux champs
//============================================================================
//
// Energie
//	
void Fragment::Set_Energie(double e)
	{
	if(A > 0)
	 {
	 double vitesse=TMath::Sqrt(2.*e/Get_Masse())*30.;
	 if(v.Mag()==0) v.SetXYZ(0.,0.,1.);
	 v.SetMag(vitesse);
	 }
	else
	 {
	 cerr << "Attribuer le nombre de nucleons avant l'energie..." << endl;
	 }
	}
//
// Theta
//	
void Fragment::Set_Theta(double theta)
	{
	double the=theta*TMath::Pi()/180.;
	v.SetTheta(the);
	}
//
// Theta
//	
void Fragment::Set_Phi(double phi)
	{
	double p=phi*TMath::Pi()/180.;
	v.SetPhi(p);
	}
//
// Masse
//	
double  Fragment::Get_Masse(void)
	{
	return A*mnuc;
	}
//
// Theta
//	
double  Fragment::Get_Theta(void)
	{
	return v.Theta()*180./TMath::Pi();
	}
//
// Phi
//	
double  Fragment::Get_Phi(void)
	{
	return v.Phi()*180./TMath::Pi();
	}
// 
// Energie cinetique
//
double Fragment::Get_Ecin(void)
	{
	return Get_Masse()*v.Mag2()/1800.;
	}
//
// Energie cinetique perpendiculaire
//
double Fragment::Get_Eperp(void)
	{
	return Get_Masse()*v.Perp2()/2.;
	}

//
// Calcul du rayon theorique
//
double Fragment::Get_Rayon(void)
	{
	return 1.2*TMath::Power((double)A,1./.3);
	}
//
// Calcul de l'energie du fondamental "Goutte Liquide"
//
double Fragment::Get_Egoutliq(void)
	{
	double av=16.;
	double as=18.;
	double ac=0.72;
	double aa=23.5;
	
	return av*A
	       -as*TMath::Power((double)A,2./.3)
	       -ac*Z*(Z-1.)/TMath::Power((double)A,1./3.)
	       -aa*TMath::Power(A-2*Z,2)/(double)A;
	}	
//
// Affichage
//
void Fragment::Affiche(void) 
	{
	char mes[80];
	sprintf(mes,"%3d, %2d : %8.2f %8.2f %8.2f\0",A,Z,v.X(),v.Y(),v.Z());
	cout << mes << endl;
	}


//
// D.Cussol 
//
// 3/11/2000:
// Creation d'une classe relative aux clusters generes par les calculs 
// N Corps
//

#ifndef Event_h
#define Event_h 
#include <iostream.h>
#ifndef ROOT_TNamed
#include "TNamed.h"
#endif
#ifndef ROOT_TVector3
#include "TVector3.h"
#endif
#include "Fragment.h"
#include "TClonesArray.h"

class Event:public TNamed
	{
// Champs Statiques
// Vecteurs contenant les valeurs des energies, des rayons, etc. en fonction de
// la taille
        public:
        static  int     nb;
        static  int     nb_crea;
        static  int     nb_dest;
	static	TClonesArray    *sfrags;

// Champs non statiques
	
	public:
		int		mult;	// nombre de fragments
		TClonesArray    *frags; //-> tableau des fragments
// Methodes
	public:
	void init_Event(void);

	public:
	Event(void);				// constructeur par defaut
	Event(char *nom);
	
	virtual ~Event(void);		// destructeur
	
	
//      Methodes d'acces direct aux champs
	virtual void   Reset(void);
	virtual void   Add_Fragment(Fragment *f);
	virtual Fragment *Get_Fragment(int i);
	virtual int    Get_Mult(void);
//      Methodes d'acces calculees
	virtual int    Get_Ztot(void);
	virtual TVector3 Get_Ptot(void);
	virtual double Get_Ecin(void);
	virtual double Get_Eperp(void);
	

	virtual void Affiche(void);
	
	ClassDef(Event,1)
	
	};
#endif

//
// D.Cussol 
//
// 21/10/2002:
// Creation d'une classe relative aux Events INDRA 
// Formation ROOT
//

#include <math.h>
#include <stdio.h>
#include "Event.h"
#include "TMath.h"
#include "Fragment.h"

ClassImp(Event)

int	Event::nb=0;
int	Event::nb_crea=0;
int	Event::nb_dest=0;
TClonesArray *Event::sfrags=0;

//============================================================================
// Methodes de base
//============================================================================
//
// Initialisation des champs de Event
// Cette methode privee n'est appelee par les createurs
//
void Event::init_Event(void)
	{
        nb++;
	mult=0;
	if(!sfrags) 
	 {
	 sfrags=new TClonesArray("Fragment",100);
	 for(int i=0;i<100;i++)
	 	Fragment *tmp = new((*sfrags)[i]) Fragment();

	 }
	frags=sfrags;
	nb_crea++;
	}

//
// Createur par default
//
Event::Event(void):TNamed()
	{
	char	*nom=new char[80];

	init_Event();
	sprintf(nom,"Event_%d\0",nb);
	SetName(nom);
	SetTitle(nom);

	delete [] nom;
	}
	
//
// Constructeur avec un nom
//
Event::Event(char *nom)
	{
	init_Event();
	SetName(nom);
	SetTitle(nom);
	}
// 
// Destructeur
//
Event::~Event(void)
       {
        nb--;
	if(nb==0) 
	 {
	 delete sfrags;
	 }
	nb_dest++;
       }

//============================================================================
// Acces directs aux champs
//============================================================================
//
// Methode d'attribution de A
//
void Event::Add_Fragment(Fragment *f)
	{
	TClonesArray &ltca=*frags;
	Fragment *tmp=(Fragment *)ltca[mult];
	if(tmp)
	 {
	 tmp->Set(f->Get_A(),f->Get_Z(),f->Get_Vit());
	 mult++;
	 }
	}
//
// Methode d'attribution de A
//
void Event::Reset(void)
	{
	if(frags) frags->Clear();
	mult=0;
	}
//
// Nombre de particules
//
int Event::Get_Mult(void)
	{
	return mult;
	}
//
// Nombre de particules
//
Fragment *Event::Get_Fragment(int i)
	{
	Fragment *f=0;
	if(frags)
	 if(i > 0 && i <= mult) 
	  {
	  f=(Fragment *)frags->At(i-1);
	  }
	 else
	  {
	  cerr << "L'indice i doit etre comprit entre 1 et " << mult << "." <<
	  endl;
	  }
	else
	 {
	 cerr << "Le TClonesArray est null..." << endl;
	 }
	return f;
	}
	
//============================================================================
// Acces calcules aux champs
//============================================================================
//
// Nombre de charges
//
int Event::Get_Ztot(void)
	{
	Fragment *f;
	int Z=0;
	if(frags)
	 for(int i=0;i<mult;i++)
	  {
	  f=(Fragment *)frags->At(i);
	  Z+=f->Get_Z();
	  }
	return Z;
	}
//
// vitesse
//	
TVector3 Event::Get_Ptot(void)
	{
	Fragment *f;
	TVector3 pt(0.,0.,0.);
	for(int i=0;i<mult;i++)
	 {
	 f=(Fragment *)frags->At(i);
	 pt+=(f->Get_Z())*(f->Get_Vit());
	 }
	return pt;
	}
// 
// Energie cinetique
//
double Event::Get_Ecin(void)
	{
	Fragment *f;
	double ect=0;
	if(frags)
	 for(int i=0;i<mult;i++)
	  {
	  f=(Fragment *)frags->At(i);
	  ect+=f->Get_Ecin();
	  }
	return ect;
	}
//
// Energie cinetique perpendiculaire
//
double Event::Get_Eperp(void)
	{
	Fragment *f;
	double ept=0;
	if(frags)
	 for(int i=0;i<mult;i++)
	  {
	  f=(Fragment *)frags->At(i);
	  ept+=f->Get_Eperp();
	  }
	return ept;
	}
//
// Affichage
//
void Event::Affiche(void)
	{
	cout << "=====================================================" << endl;
	cout << "Mult : " << mult << endl;
	if(frags)
	 for(int i=0;i<mult;i++)
	  {
	  cout << i+1 << " -> ";
	  ((Fragment *)frags->At(i))->Affiche();
	  }
	cout << endl;
	}



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:15 MET