I have applied your advice, although the heap contains plenty of objects
related to the histogram.
I observe the following after 10 iterations :
- with my version (no pointer and use of the static member function Open)
Total allocated memory : 77972
- with your proposal (with pointer, without the function Open,
but with constructor and destructor each time)
Total allocated memory : 73692
So my gain is 5.8% :-(
If you look carefully at the heap, you will see that a TFile has appeared!
Anyway I have put in comments all the histogram operation (creation and
read out) and got down to 37966 :-|
The heap now contains of course only the TFile class.
In conclusion, it is not only a problem with TFile, AND the problem with
TFile is still not solved.
By looking shortly at the header of TFile, I have noticed some static
declarations :
static Double_t fgBytesWrite;
static Double_t fgBytesRead;
static const Int_t kBegin;
static const Char_t kUnits;
Some are also in TDirectory.h from which TFile derivates.
Could these variables responsible for the memory leak ?
Thanks,
David Gourio
On Mon, 5 Apr 1999, Rene Brun wrote:
>Hi David,
>If you look at the prototype of TFile::Open, you will see that this
>is a static function returning a TFile object.
>I have modified your function ProcessFile such that you do not get
>a memory leak.
>
>Rene Brun
>
>
>void ProcessFile(char * RootFileName) {
>
> TFile *RH_File;
>
> // Dummy histogram to be written in the root file
> TH1F DummyHisto("Dummy", "I am empty", 100, 0., 1.);
>
> // Open the file, take care if it already exists
> if (Lili.AccessPathName(RootFileName) ) {
> // File does not exist yet.
> RH_File = new TFile(RootFileName,"CREATE","Gros appetit");
> }
> else {
> // File already exists
> RH_File = new TFile(RootFileName,"UPDATE");
> }
>
> // Write down in the file the dummy histogram, overwrite instead of
> // creating a new version of the object
> DummyHisto.Write(DummyHisto.GetName(), TObject::kOverwrite);
>
> RH_File->Close();
> delete RH_File;
>}
>
>
>On Wed, 31 Mar 1999, David Gourio wrote:
>
>> Hi Rooters,
>>
>> In the following example, I just open a root file, write down a dummy
>> histogram and close it. I avoid any dynamical allocation.
>> THF1 and TFile are declared in a subfunction of the main program (and not
>> as static), they are consequently local and have a lifetime related to the
>> execution of the function.
>> Nevertheless, the allocated memory gets larger as I reexecute the
>> function (if I have well understood how TStorage works).
>>
>> By looking closely at the created root classes, I see that some classes
>> remain on the heap, mainly originating from the histogram..., but also
>> from the TFile.
>> I have removed them by hand, but it doesn't even really help.
>>
>> So is it a bug (from me?) or a feature ? In both cases, how to
>> properly clean the memory ?
>>
>> The source file should be compiled with a standart Makefile
>> I use version 220 of Root.
>>
>> Thanks,
>> best regard,
>>
>> David Gourio
>> ========================================================================
>> Mail : GSI, Abteilung KP3 D-64291 Darmstadt
>> E-Mail : D.Gourio@gsi.de
>> Phone : +49 6159 71 27 79
>> Fax : +49 6159 71 29 89
>>
>>
>>
>>
>> ------------------------------Source---------------------------------
>> #include <iostream.h>
>>
>> #include <TROOT.h>
>> #include <TUnixSystem.h>
>> #include <TH1.h>
>> #include <TFile.h>
>>
>>
>> char * PrintBool(Bool_t MyBoolean) {
>> if (MyBoolean) return "True";
>> else return "False";
>> }
>>
>> void ProcessFile(char * RootFileName) {
>>
>> TUnixSystem Lili;
>>
>> TFile RH_File;
>>
>> // Dummy histogram to be written in the root file
>> TH1F DummyHisto("Dummy", "I am empty", 100, 0., 1.);
>>
>> // Open the file, take care if it already exists
>> if (Lili..AccessPathName(RootFileName) ) {
>> // File does not exist yet.
>> RH_File.Open(RootFileName,"CREATE","Gros appetit");
>> }
>> else {
>> // File already exists
>> RH_File.Open(RootFileName,"UPDATE");
>> }
>>
>> // Write down in the file the dummy histogram, overwrite instead of
>> // creating a new version of the object
>> DummyHisto.Write(DummyHisto.GetName(), TObject::kOverwrite);
>>
>> RH_File.Close();
>> }
>>
>>
>>
>> int main() {
>>
>> TROOT MyRoot("xx", "xx xx");
>>
>> // For checking the objects still in memory...
>> TObject * obj;
>> TIter * AllClassesList;
>>
>> // Root file name
>> char * RootFileName="gargantua.root";
>>
>> // Create and enable statistics of the heap
>> TStorage MyHeap;
>> MyHeap.EnableStatistics();
>>
>> // Print out the memory state once before
>> cout << "Before\n";
>> MyHeap.PrintStatistics();
>>
>>
>> // Main loop : write 10 times in the file
>> for ( int i_loop=0 ; i_loop<10 ; i_loop++ ) {
>>
>>
>> // Open, fill and close the root file
>> ProcessFile(RootFileName);
>>
>>
>> // Print out the memory state
>> cout << "After " << i_loop+1 << " pass\n";;
>> MyHeap.PrintStatistics();
>>
>>
>> // Print out list of root classes
>> cout << "------List of current root classes----------\n";
>> AllClassesList = new TIter(MyRoot.GetListOfClasses());
>> while ( (obj = AllClassesList->Next()) ) {
>> cout << obj->GetName() << " "
>> << "On Heap:" << PrintBool(obj->IsOnHeap()) << " "
>> << "Zombie:" << PrintBool(obj->IsZombie()) << endl;
>> }
>> delete AllClassesList;
>>
>> }
>>
>>
>>
>> // Print out list of root classes and delete them
>> cout << "--------List of current root classes----------\n";
>> AllClassesList = new TIter(MyRoot.GetListOfClasses());
>> while ( (obj = AllClassesList->Next()) ) {
>> cout << obj->GetName() << " "
>> << "On Heap:" << PrintBool(obj->IsOnHeap()) << " "
>> << "Zombie:" << PrintBool(obj->IsZombie()) << endl;
>> // Suppress all classes on the heap
>> delete obj;
>> }
>> delete AllClassesList;
>>
>>
>> }
>>
>>
>>
>>
>
>
========================================================================
Mail : GSI, Abteilung KP3 D-64291 Darmstadt
E-Mail : D.Gourio@gsi.de
Phone : +49 6159 71 27 79
Fax : +49 6159 71 29 89