Write in a file without memory leak

David Gourio (gourio@gsi.de)
Wed, 31 Mar 1999 16:49:57 +0200 (CED)


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;

}