How to clean up TImage? Getting memory leaks

Hi

I am using the TImage class in C++ to grab an image of a pad (using FromPad()). I then also use the GetArgbArray() method to get the bitmap’s ARGB pixel array. However, I am unsure about how to clean up the TImage after using it.

The code basically looks like this:

TObject *aClone
TImage *imgH = TImage::Create();

while()
  {
	aClone	   = aPad1->Clone();	// Clone from a pad
	aPadClone  = (TPad*)aClone;		
	aPadClone->SetPad(0,0,1,1);
		
	aPad2->cd();		
	aPadClone->Draw();		// Draw the clone

	imgH->FromPad(aPadClone);	// Get image
	imgH->Mirror();

	UInt_t *histImage1RGBA;		// Get image's ARGB pixels
	histImage1RGBA	= imgH->GetArgbArray();
	/*
		Use the array histImage1RGBA
	*/
	delete aClone;
  }

This code is called repeatedly. I’ve included a script that almost does what I got in C++. In both implementations (C++ and the script) using ROOT 5.25 under Windows XP, and Window’s PerfMon using Private Bytes of the processes, the memory allocation keeps creeping up.

When I debugged the code, it is the memory allocation in FromPad() and GetArgbArray() methods that is not being released.

When I looked at the code for the FromPad() method - I see a call to the private method DestroyImage(), so I assumed that the FromPad() would destroy/delete the previous memory allocated to an image and it’s associated arrays (such as the ARGB array).

Is there something I need to add to explicitly delete the image’s allocated memory? I even tried to SetImage() to a blank array, but that still had memory leaks.
TestImage2.C (1.06 KB)

Thanks for the code. I’ll have a look.

I tried your example. I see the size of the root.exe increasing when your loop in running. But when I comment the line…

h->FillRandom("gaus",1000);

…inside the loop then the size seems stable. Can you confirm ?

Hi

Sorry about that I have added a h->Reset() before that statement, but I’ve posted the wrong version of the script.

Either way, I still see a memory leak. Even with the h->FillRandom() commented out.

I’ve attached a snapshot of PerfMon showing private bytes for the root process. This is with the FillRandom() commented out, and I’ve increased the delay to 2 seconds to show the memory allocation steps more clearly.

In the C++ program, it simply runs out of memory and then crashes.


Here is the PerfMon graph for the same script with the TImage methods commented out:

	//imgH->FromPad(aPadClone);
	//imgH->Mirror();

	//UInt_t *histImage1RGBA;
	//histImage1RGBA		= imgH->GetArgbArray();


ok, i’ll look again.

I also commented the TImage stuff on Mac … and even with this commented I see the memory growing …

Well, I’m not sure about the Mac. I’m using the Win32 libraries on Windows XP, and I’ve narrowed the memory leak down to the TImage FromPad() and GetArgbArray().

Can you confirm that the code (as represented in the script above) uses TImage correctly? As in, there are no other explicit ways to clean up after using TImage?

If the usage is correct, then what next?

With the following macro the memory usage is stable on Mac and LInux.

TestImage2 ()
{
   TCanvas *c1	  = new TCanvas("c1","c1",800,600);; 
   TPad	   *p1 = new TPad("p1","p1",0,0,1,0.5);

   TH1F *h = new TH1F("gaus", "gaus", 100, -5, 5); 
   
   h->FillRandom("gaus", 10000); 
   h->Draw(); 

   UInt_t histImage1RGBA;		

   TImage *imgH = TImage::Create(); 
   TObject *aClone;
   TPad *aPadClone;

   while (true) {
      p1->cd();
      h->FillRandom("gaus",1000);
      p1->Modified();
      p1->Update();

      imgH->FromPad(p1);
      imgH->Mirror();

      histImage1RGBA = imgH->GetArgbArray();

      gSystem->Sleep(10);
   }
}

OK

I ran the script you provided on a Windows XP with 3GB of physical RAM, and after a couple of minutes I got this in CINT:

ROOT 5.25/02 (trunk@30530, Sep 29 2009, 15:28:19 on win32)

CINT/ROOT C/C++ Interpreter version 5.17.00, Dec 21, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] .x TestImage2.C
Exception: bad allocation
Error: Symbol G__exception is not defined in current scope C:\TestImage\TestImage2.C(23)
Error: type G__exception not defined FILE:C:\TestImage\TestImage2.C LINE:23
*** Interpreter error recovered ***
root [1]

I’ve attached the graph from PerfMon, and the Task Manager to show how the memory allocation is not freed up.

I’ve also ran the script on another Windows XP, a Windows Vista, and on a Windows 7 installation - all had the same problem!

Could someone with a Windows installation help with this please?

It seems obvious to me that there is something wrong here.
I’m willing to help in whatever way…




I do not have any Windows machine ready to use right now my crashes and I had not time yet to reinstall it. I’ll ask a colleague to try.

We just tried on a windows machine. FromPad is the faulty method because the following macro is enough to show the memory leak:

TestImage2 () 
{ 
   TCanvas *c1     = new TCanvas("c1","c1",800,600);; 
   TPad      *p1 = new TPad("p1","p1",0,0,1,0.5); 

   TH1F *h = new TH1F("gaus", "gaus", 100, -5, 5); 
    
   h->FillRandom("gaus", 10000); 
   h->Draw(); 

   TImage *imgH = TImage::Create(); 
  
   while (true) { 

      imgH->FromPad(p1); 
 
      gSystem->Sleep(10); 
   } 
} 

We do not have any answer yet. We need to investigate.

OK great that it’s been found, and narrowed down.

I have submitted a bug report on savannah - I’ll update the item and indicate that it’s the FromPad() method

Post the little example I end up with.

I did that - thanks

Now fixed thanks to Bertrand. See: savannah.cern.ch/bugs/?58287

Excellent! Quick turn around!

I grabbed that trunk and compiled it (with some difficulty), testing the C++ application now, but the script is definitely not leaking.

Thank you