Memory leak creating TGraph in a loop

Dear rooters,

I am trying to write a root based application displaying waveforms of a fast digitizer. The waveforms of one event and each channel of the digitizer should be saved in a TMultiGraph. This multigraph should be displayed in a TCanvas and updated (efficently) periodically. The problem is, that creating a TGraph with the new operator in the event loop, will sooner or later cause a memory leakage. If one deletes the pointer of the TGraph at the end of the loop, it will also be removed from TMultiGraph and could not displayed any more.

I wrote a little macro to demonstrate the issue.

// simple  macro to test if a TMultiGraph can be reseted

//std. cpp includes
#include <vector>

void TestMultiGraph()
{   //Define variables
    const int   NumChannels = 4,
                NumSamples  = 1000,
                NumEvents   = 400000,
                kUpdate	    = 100;
                
    //Define TMultiGraph
    TMultiGraph *mg = new TMultiGraph();
        mg->SetMinimum(-0.5);
        mg->SetMaximum(0.5);

    //Declare TGraph
    TGraph *graph;

    //define x and y pointers to vector<float>
    vector <float> *pSignal = new vector <float>();
    vector <float> *pTime   = new vector <float>();

    //define TCanvas to display the multigraph
    TCanvas *c1 = new TCanvas();
        c1->cd(1);

    //fill the x vector
    for (int j=0; j<NumSamples; j++)
        pTime->push_back(j);

    //define variables defining properties of the created signal (logic)
    unsigned int BaseLine = 200, Width = 300, event = 0;
    double Offset = 0.4;

    //event loop
    while (event<NumEvents)
    {   // loop creating NumChannels y vectors
        for (int channel=0; channel<NumChannels; channel++)
        {   //generate signal and fill it to pSignal
            GenerateSignal( pSignal, NumSamples, BaseLine, Width, Offset);
            //create TGraph
            graph = new TGraph(pSignal->size(),
                &(pTime->at(0)),
                &(pSignal->at(0)));
            //set channel dependent line color
            graph->SetLineColor(channel+2);
            //add TGraph to TMultiGraph
            mg->Add(graph);
            //delete the pointer to TGraph
//            delete graph;
        }
        //if the TMultiGraph was filled for the first time --> draw it
        if (event==0) 
        mg->Draw("AL");
        else if (event%kUpdate==0)
        {   gPad->Modified();
            gPad->Update();
        }
        //reset TMultiGraph
        mg->GetListOfGraphs()->Clear();

        event++;
    }
}

//______________________________________________________________________________
void GenerateSignal(vector <float> *pSignal, int Length, int BaseLine,
                    int Width, double Offset)
{   // method to create a logic signal with noise
////////////////////////////////////////////////////////////////////////////////

//          <------------------------Length--------------------------------->
//          <---BaseLine---->
//  Offset  ________________            _____________________________________
//  H                       |           |
//  e                       |           |
//  i                       |           |
//  g                       |           |
//  h                       |           |
//  t                       -------------
//                           <--Width-->

////////////////////////////////////////////////////////////////////////////////
    double Height = gRandom->Uniform(0,-0.8);
    double noise;

    //clear vector
    pSignal->clear();

    for (int sample=0; sample<Length; sample++)
    {   //Baseline
        if (sample<BaseLine)
        {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
        //signal
        else if (sample<BaseLine+Width)
        {   noise = gRandom->Gaus(Offset+Height, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
        //rest
        else
        {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
    }

    return;
}

Is there a possiblilty to avoid the memory leackage?
TestMultiGraph.cpp (3.41 KB)

If one uses TGraph::SetPoint() and loops over all samples, the memory leakage is avoided. But is this a efficient way to do that?

// simple  macro to test if a TMultiGraph can be reseted

//std. cpp includes
#include <vector>

void TestMultiGraph()
{   //Define variables
    const int   NumChannels = 4,
                NumSamples  = 1000,
                NumEvents   = 400000,
                kUpdate	    = 1;
                
    //Define TMultiGraph
    TMultiGraph *mg = new TMultiGraph();
        mg->SetMinimum(-0.5);
        mg->SetMaximum(0.5);

    //declare TGraphArray
    TGraph *graph[NumChannels];
    //define TGraphArray
    for (int i=0; i<NumChannels; i++)
        graph[i] = new TGraph();

    //define x and y pointers to vector<float>
    vector <float> *pSignal = new vector <float>();
    vector <float> *pTime   = new vector <float>();

    //deine TCanvas to display the multigraph
    TCanvas *c1 = new TCanvas();
        c1->cd(1);

    //fill the x vector
    for (int j=0; j<NumSamples; j++)
        pTime->push_back(j);

    //define variables defining properties of the created signal (logic)
    unsigned int BaseLine = 200, Width = 300, event = 0;
    double Offset = 0.4;

    //event loop
    while (event<NumEvents)
    {   // loop creating NumChannels y vectors
        for (int channel=0; channel<NumChannels; channel++)
        {   //generate signal and fill it to pSignal
            GenerateSignal( pSignal, NumSamples, BaseLine, Width, Offset);
            //set channel dependent line color
            for (int sample=0; sample<pTime->size(); sample++)
                graph[channel]->SetPoint(sample, 
                                         pTime->at(sample), 
                                         pSignal->at(sample));
                                         
            graph[channel]->SetLineColor(channel+2);
            //add TGraph to TMultiGraph
            mg->Add(graph[channel]);
        }
        //if the TMultiGraph was filed fpr the first time --> draw it
        if (event==0) 
            mg->Draw("AL");
        else if (event%kUpdate==0)
        {   gPad->Modified();
            gPad->Update();
        }
        //reset TMultiGraph
        mg->GetListOfGraphs()->Clear();
        
        gSystem->ProcessEvents();

        event++;
    }
}

//______________________________________________________________________________
void GenerateSignal(vector <float> *pSignal, int Length, int BaseLine,
                    int Width, double Offset)
{   // method to create a logic signal with noise
////////////////////////////////////////////////////////////////////////////////

//          <------------------------Length--------------------------------->
//          <---BaseLine---->
//  Offset  ________________            _____________________________________
//  H                       |           |
//  e                       |           |
//  i                       |           |
//  g                       |           |
//  h                       |           |
//  t                       -------------
//                           <--Width-->

////////////////////////////////////////////////////////////////////////////////
    double Height = gRandom->Uniform(0,-0.8);
    double noise;

    //clear vector
    pSignal->clear();

    for (int sample=0; sample<Length; sample++)
    {   //Baseline
        if (sample<BaseLine)
        {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
        //signal
        else if (sample<BaseLine+Width)
        {   noise = gRandom->Gaus(Offset+Height, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
        //rest
        else
        {   noise = gRandom->Gaus(Offset, fabs(0.01*Height));
            pSignal->push_back(noise);
        }
    }

    return;
}