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