Re: [ROOT] Memory leak when using TClonesArray::ExpandCreate

From: Rene Brun (Rene.Brun@cern.ch)
Date: Tue Jul 22 2003 - 09:12:56 MEST


Hi John,

I cannot reproduce your problem. Here is a transcript of my session.

Rene Brun

root [0] gSystem.Load("libPhysics")
(int)0
root [1] .L MyNuc.cxx+
Info in <TUnixSystem::ACLiC>: creating shared library
/home/brun/roottest/./MyNuc_cxx.so
root [2] .L test.C+
Info in <TUnixSystem::ACLiC>: creating shared library
/home/brun/roottest/./test_C.so
root [3] test()
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
Creating object list....
done
fNb_Objects=1, size of list=1
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
fNb_Objects=6, size of list=6
fNb_Objects=6, size of list=6
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
 ++ Calling default ctor ++
Calling AddToObjList...
AddToObjList............
done
fNb_Objects=8, size of list=6
root [4] .q


Frankland John wrote:
> 
> Hello Rene
> 
> Rene Brun wrote:
> 
> > Hi John,
> >
> > You are not drawing the right conclusion from your observation
> > with MyNuc::GetNbObj. Let me explain.
> >
> > The TClonesArray is based on the standard C++ "new with placement".
> > When calling new(a[i]) myclass(), the following happens:
> >  -if a[i] is null, an object of myclass is allocated space and the
> > myclass
> > constructor is called.
> >  - if a[i] is not null, your myclass constructor is called. No need to
> > allocate space (time consuming). The object is simply initialized by the
> > statements in your constructor, overwriting the values of the data
> > members
> > created by a previous call to the constructor. The address of the object
> > is the one previously stored at a[i] (new with placement).
> > In your case your class MyNuc records only the number of calls
> > to your myclass constructor. It does not record the number of times
> > a new object has been allocated.
> >
> >
> >
> >
> In order to see this happening, I modified the MyNuc class as in the
> attachment.
> I added a static TList to which I add the "this" pointer every time the ctor
> is called, only if
> the object pointed to is not already in the list. However, despite protecting
> all possible
> cases of pointer abuse, when I compile and run the test.C script attached (.L
> libPhysics.so,
> .L MyNuc.cxx+, then .L test.C+) it ends up in a segmentation fault:
> 
> root [0] .L libPhysics.so
> root [1] .L MyNuc.cxx+
> Info in <TUnixSystem::ACLiC>: creating shared library
> /home/john/lib//home/john/ClonesTests/./MyNuc_cxx.so
> root [2] .L test.C+
> root [3] test()
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> Creating object list....
> done
> fNb_Objects=1, size of list=1
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> done
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> done
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> done
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> done
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> done
> fNb_Objects=6, size of list=6
> fNb_Objects=6, size of list=6
>  ++ Calling default ctor ++
> Calling AddToObjList...
> AddToObjList............
> 
>  *** Break *** segmentation violation
>  Generating stack trace...
> /usr/bin/c++filt: unknown demangling style `gnu-new-abi'
> 
> I can't see why ! Can somebody please help me ?
> My last CVS update/compile was July 14th, on Linux RH8 with gcc3.2.
> 
> Thanks a lot
> John
> 
> --
> 
>                      [ganil logo]
> 
>                      John D. Franklandtel: +33
>                      Beam Coordinator (0)231454628
>                      GANIL            fax: +33
>                      B.P. 55027       (0)231454665
>                      14076 CAEN Cedex
>                      05
> 
>     -----------------------------------------------------------------------
> #ifndef __MyNuc_H
> #define __MyNuc_H
> 
> #include "TLorentzVector.h"
> 
> class MyNuc : public TLorentzVector
> {
>                         UChar_t fZ;
>                         UChar_t fA;
>                         static Int_t fNb_Objects;
>                         static TList* fObjList;
>                         void AddToObjList(TObject*);
> 
>         public:
>                         MyNuc();
>                         MyNuc(const MyNuc &);
>                         MyNuc(int z, int a);
>                         virtual ~MyNuc();
> 
>                         void SetZ(int z){fZ=(UChar_t)z;}
>                         void SetA(int a){fA=(UChar_t)a;}
>                         Int_t GetZ() const;
>                         Int_t GetA() const;
>                         Int_t GetNbObj(Option_t *opt="");
>                         void SetPxPyPz(Float_t px, Float_t py, Float_t pz);
>                         void Clear(Option_t *opt="");
> 
>                         ClassDef(MyNuc,1) // Just for tests
> };
> 
> #endif
> 
>     -----------------------------------------------------------------------
> #include "MyNuc.h"
> #include <Riostream.h>
> 
> ClassImp(MyNuc)
> 
> //__________________________________________________________________
> //MyNuc
> //For testing TClonesarray behaviour
> //
> 
> Int_t MyNuc::fNb_Objects=0;
> TList *MyNuc::fObjList=0;
> 
> MyNuc::MyNuc()
> {
>         cout << " ++ Calling default ctor ++ " << endl;
>         fZ = fA = 0;
>         fNb_Objects++;
>         cout << "Calling AddToObjList..." << endl;
>         AddToObjList(this);
> }
> 
> void MyNuc::AddToObjList(TObject* obj)
> {
>         //Add pointer to object to static list if the pointer is not already in the list
>         cout << "AddToObjList............" << endl;
>         if(!fObjList) {
>                 cout << "Creating object list...." << endl;
>                 fObjList=new TList;
>         }
>         if(obj){
>                 if(!fObjList->FindObject(obj)) fObjList->Add(obj);
>         } else {
>                 cout << "(the 'this' pointer is NULL)........."  << endl;
>         }
>         cout << "done" << endl;
> }
> 
> MyNuc::MyNuc(int z, int a)
> {
>         fZ = (UChar_t)z;
>         fA = (UChar_t)a;
>         fNb_Objects++;
>         AddToObjList(this);
> }
> 
> MyNuc::MyNuc(const MyNuc &obj)
> {
>         fZ = obj.GetZ();
>         fA = obj.GetA();
>         fNb_Objects++;
>         AddToObjList(this);
> }
> 
> MyNuc::~MyNuc()
> {
>         fNb_Objects--;
>         if(!fNb_Objects) delete fObjList;
> }
> 
> Int_t MyNuc::GetZ() const
> {
>         return (Int_t)fZ;
> }
> 
> Int_t MyNuc::GetA() const
> {
>         return (Int_t)fA;
> }
> 
> Int_t MyNuc::GetNbObj(Option_t *opt)
> {
>         if(strcmp(opt,"")) cout << "fNb_Objects=" << fNb_Objects << ", size of list=" << fObjList->GetSize() << endl;
>         return fNb_Objects;
> }
> 
> void MyNuc::Clear(const Option_t *opt)
> {
>         TLorentzVector::Clear(opt);
>         fZ=fA=0;
> }
> 
> void MyNuc::SetPxPyPz(Float_t px, Float_t py, Float_t pz)
> {
>         Float_t mass = 931.5*GetA();
>         TLorentzVector::SetXYZM(px,py,pz,mass);
> }
> 
>     -----------------------------------------------------------------------
> #include "MyNuc.h"
> #include "TClonesArray.h"
> 
> void test()
> {
>         MyNuc a;
>         a.GetNbObj("print");
> 
>         TClonesArray tca("MyNuc", 50);
> 
>         tca.ExpandCreate(5);
>         a.GetNbObj("print");
>         tca.Clear("C");
> 
>         tca.ExpandCreate(3);
>         a.GetNbObj("print");
>         tca.Clear("C");
> 
>         tca.ExpandCreate(5);
>         a.GetNbObj("print");
>         tca.Clear("C");
> }



This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:13 MET