Memory leak when projecting a THnSparseD

Hi,

I want to project a many dimensional sparse histogram to 1 dimensional sparse histo.
While doing this I found a memory leak in my program when calling the Projection function.

I provide with a simple code example to reproduce

void macro() {
        Int_t bins[5] = {100,100,100,100,100};
        Double_t xmin[5] = {0., 0.,0.,0.,0.};
        Double_t xmax[5] = {1.,1.,1.,1.,1.};
        auto sp=new THnSparseD("t","t",5,bins,xmin,xmax);


        for(auto i=0;i<1000000000;i++)
        {
                //              Double_t a[5]={0.00001*i,0.00001*i,0.00001*i,0.00001*i,0.00001*i};

                //              sp->Fill(a,1.0);
                int b=0;
                /*              for(auto k=0;k<5;k++)
                                {

                                if(k!=b)
                                {
                                const auto proj_bin=20;
                                sp->GetAxis(k)->SetRange(proj_bin,proj_bin);
                                }

                                }

                                sp->GetAxis(b)->SetRange(1,100);*/
                const auto hist=sp->Projection(1,&b);
                delete hist;
        }

}

How can it be that the memory usage grow if I am deleting the object after I create it.
This behavior also happens when projecting to 2 dimensions;
Thank you in advance for any help;

_ROOT Version:6.24/06
_Platform:linuxx8664gcc

Hi @Eddy_Glezz ,
thank you for the report, I can see the memory leak even with ROOT’s master branch, and valgrind massif points here for the source of the allocations:

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 51 259,628,611,990    3,008,077,216    2,804,389,611   203,687,605            0
93.23% (2,804,389,611B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->91.16% (2,742,099,104B) 0x4B77D41: TStorage::ObjectAlloc(unsigned long) (TStorage.cxx:330)
| ->91.16% (2,742,073,800B) 0x10C48A: TObject::operator new(unsigned long) (TObject.h:167)
| | ->91.14% (2,741,588,856B) 0x59CB993: THnBase::Init(char const*, char const*, TObjArray const*, bool, int) (THnBase.cxx:204)
| | | ->91.14% (2,741,588,856B) 0x59CB899: THnBase::CloneEmpty(char const*, char const*, TObjArray const*, bool) const (THnBase.cxx:185)
| | |   ->91.14% (2,741,588,856B) 0x59CDD22: THnBase::ProjectionAny(int, int const*, bool, char const*) const (THnBase.cxx:601)
| | |     ->91.14% (2,741,588,856B) 0x10C683: THnBase::ProjectionND(int, int const*, char const*) const (THnBase.h:257)
| | |       ->91.14% (2,741,588,856B) 0x10C961: THnSparse::Projection(int, int const*, char const*) const (THnSparse.h:155)
| | |         ->91.14% (2,741,588,856B) 0x10C37E: macro() (repro.cpp:28)
| | |           ->91.14% (2,741,588,856B) 0x10C3FD: main (repro.cpp:34)
| | |
| | ->00.02% (484,944B) in 1+ places, all below ms_print's threshold (01.00%)
| |
| ->00.00% (25,304B) in 1+ places, all below ms_print's threshold (01.00%)
|
->02.07% (62,290,507B) in 3162 places, all below massif's threshold (1.00%)

Let’s ping @moneta :slight_smile:

(EDIT: I am not sure why your delete does not free this memory, intuitively it should, there must be something in the code that I’m missing but I did not dig too much).

(EDIT 2: Never mind, this PR should remove the memory leak: https://github.com/root-project/root/pull/9997 )

3 Likes

This is now fixed in ROOT nightly builds (future v6.28) and a backport of the fix will be included in v6.26.02.

1 Like