Graph initialized in loop: annoying "memory leak" message

Dear Rooters,

I apologize if the following issue sounds trivial, I am an occasional root user (v5.30.03, installed on macos 10.7). Yet, I didn’t find any solution among the previous posts/answers.

I am using a TGraph object, which I need to reinitialize inside a loop from another TGraph. When drawing the source TGraph before the loop, then I systematically get the following warning message:
Warning in TROOT::Append: Replacing existing TH1: Graph (Potential memory leak).

The warning message does not appear, when “Draw()” is not called. From the ouptut, I can hardly see where the leak happens. Anyway, this is also annoying since I keep my code’s outputs, which then get very heavy …

My code is not easy to copy-paste here, but I was able to reproduce this from a short template that I attach.

test_root_pb.cpp (1.6 KB)

Many thanks in advance for helping me solve that issue.

All the best, Julien.

Try:

{
  TPostScript *myps = new TPostScript("test_root.ps",111);
  TCanvas c1("c1","c1",500,500);

  TH2D *hh = new TH2D("hres","hres",2,0,100,2,0,110);
  hh->SetXTitle("x");
  hh->SetYTitle("y");

  double x,y;

  int i,j,Ni=10,Nj=100;

  TGraph *grlocal = new TGraph(Nj+1);
  TGraph *grtest  = new TGraph(Nj+1);

  for(i=0;i<=Ni;++i){

    for(j=0;j<=Nj;++j){
      x = j;
      y = 2*i+j;
      grlocal->SetPoint(j,x,y);
      grtest->SetPoint(j,x,2*y);
    }

    hh->Draw();

    // When the line below is commented, there is no warning message anymore.
    grlocal->Draw("l");

    // For some reason, I have to initialize grtest at each step in a loop
    for(j=0;j<3;++j){
      grtest = grlocal;
      //
      // ... here, call any function using grtest and potentially modifying it
      //
      grtest->SetLineColor(kRed);
      grtest->SetLineStyle(2);
      grtest->Draw("l");
      c1.Update();
      }
  }

  myps->Close(); delete myps; delete hh;
}

Hi Couet,

Using a pointer makes it, indeed, many thanks for sending me the trick. Making this change has still two drawbacks, though some minor ones which I will easily accomodate:

*) I have to change many functions I wrote before (I used to compile and run this code on another pc before — ubuntu + root 5.16 — on which this warning message never showed up) ;
*) this doesn’t explain me why this warning message appears. Is there really a memory leakage ?

Anyway, thank you for the impressively quick solution !

Best, Julien.

Yes the way you wrote it was wrong.
TGraph creates internally a pointer to a histogram to draw the frame.
Not using pointers created many histograms never deleted
yes the leak was real.

Olivier, your modified code creates leaks, too:

  1. you call “new TGraph” twice, but you never “delete” them,
  2. the line “grtest = grlocal;” is not what the original line was doing - moreover, the old “*grtest” TGraph (created with “new”) is not accessible any more.

The point 1. could be solved by something like:

// in the end of the routine, just before "return"
if (grlocal) delete grlocal;
if (grtest) delete grtest;

The point 2. could be solved by something like:

// instead of "grtest = grlocal;"
if (grtest) delete grtest;
grtest = new TGraph(*grlocal);

The purpose of my code was to show how to get ride of the warning messages.
Thanks for the update.

Many thanks to both of you for your complementary answer. What was not easy to figure out is that the leakage occurred only when Draw() was called — Couet nicely explained why. Now, managing the memory allocation with pointers is indeed slightly more subtle than with the objects themselves (at least for non-experts, as I am), as emphasized by Pepe — this is why I was not using pointers in my code in a systematic way, which I understand was correct for my TGraph as long as Draw() was not called. Anyway, I am quite happy with the solutions you sent, but if by chance you know a way to delete the internal histogram pointer created when a non-pointer graph is drawn (which was at the origin of the leakage), I would also certainly be interested. Cheers, JL.

The internal histogram cannot be deleted.

Actually, I think you can delete the internal histogram if you like (replace “->” with a “.” if “MyGraph” is not a pointer):

if (MyGraph->GetHistogram()) { delete MyGraph->GetHistogram(); MyGraph->SetHistogram(0); }

The real problem is, however, that it’s not only that histogram that creates the memory leak.
There are the “[fNpoints] arrays of X/Y/Z points” and possibly also the “list of functions (fits and user)” which are not taken care at all when you “overwrite” the graph.

The histogram will be created each time you do a Draw(0 …

Sorry, I was not precise.
A lot of operations will automatically “create” that histogram if it’s not already present (even doing “MyGraph->GetHistogram()” will do this).
I meant, you could delete the histogram and immediately afterwards “overwrite” the graph.
But that would still create a memory leak (unrelated to the histogram itself).