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 <ca=*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