Re: Write in a file without memory leak

From: David Gourio (gourio@gsi.de)
Date: Tue Apr 06 1999 - 14:40:49 MEST


Bonjour Rene,

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



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:31 MET