GSLMultiFit Memory Leak with ROOT::Fit::Fitter?

I am attempting to use the ROOT::Fit::Fitter class in combination with the GSLMultiFit minimizer and am running into a memory leak which seems to be inherent to the minimizer (as best as I can tell). I have been looking for ways around this issue without much success (I do not wish to change minimizers as this is threadsafe and provides both accurate and fast results) so any insight would be greatly appreciated. I am running Root 6.22.02 and please find a code snippet and valgrind report below:

Code snippet: //This code snippet is taken from a function which is called within a loop over many iterations.
ROOT::Math::WrappedMultiTF1 fitFunction(*f_fit, 3 ); //f_fit is a TF1
ROOT::Fit::BinData data(31,1);
ROOT::Fit::FillData(data,h_data); //h_data is a histogram of data filled earlier
ROOT::Fit::Chi2Function *EPChi2 = new ROOT::Fit::Chi2Function(data, fitFunction);
ROOT::Fit::Fitter fitter;
fitter.Config().MinimizerOptions().SetMinimizerType(“GSLMultiFit”);
fitter.Config().SetParamsSettings(3,params); //params is set up and is an array of 3 doubles
fitter.FitFCN(*EPChi2,0,data.Size(),true);

When running this over many iterations i notice a significant memory leak, and when checking with valgrind I can trace it back to:
==25373== 252,320 (116,544 direct, 135,776 indirect) bytes in 1,214 blocks are definitely lost in loss record 22,404 of 22,439
==25373== at 0x4C2AE3B: operator new(unsigned long) (vg_replace_malloc.c:422)
==25373== by 0x2068B2BA: ROOT::Fit::Chi2FCN<ROOT::Math::IBaseFunctionMultiDimTempl, ROOT::Math::IParametricFunctionMultiDimTempl >::Clone() const (Chi2FCN.h:112)
==25373== by 0x20656C89: ROOT::Math::BasicMinimizer::SetFunction(ROOT::Math::IBaseFunctionMultiDimTempl const&) (BasicMinimizer.cxx:243)
==25373== by 0x3381C845: ROOT::Math::GSLNLSMinimizer::SetFunction(ROOT::Math::IBaseFunctionMultiDimTempl const&) (GSLNLSMinimizer.cxx:174)
==25373== by 0x206841C4: ROOT::Fit::Fitter::DoInitMinimizer() (Fitter.cxx:857)
==25373== by 0x20684DAE: ROOT::Fit::Fitter::FitFCN() (Fitter.cxx:338)

It appears to me that it internally it is cloning the fit function but then not deleting the clone when finished. I have not been able to find a way to access and delete this clone or avoid this effect as it appears to happen at the time of fitting, though perhaps my interpretation is incorrect.

Hi,
In principle the function set in BasicMinimizer::SetFunction should be deleted in the destructor.
To investigate your problem, can you provide to me easly the full code ? If not I can try to reproduce it using your example above

Thank you for reporting this

Lorenzo

Hi Lorenzo,

Although the main code is not able to be easily passed along as it is part of a larger undertaking, I produced a simplified example file that will reproduce this leak in the valgrind report.
forcheck.C (1.0 KB)

Hi,
forcheck1.C (1.1 KB)
try the attached modified forcheck1.C

Hi smgrig,

Thank you for the modified file. This was actually the original version of the implementation I had been working with. In my initial investigation I switched some objects to pointers as an attempt to resolve the issue without any luck, but for certainty I ran the forcheck1.C you posted here and it returns the same memory leak issue, as shown in valgrind below:
==19855== 4,136 (1,920 direct, 2,216 indirect) bytes in 20 blocks are definitely lost in loss record 11,020 of 11,919
==19855== at 0x4C2AE3B: operator new(unsigned long) (vg_replace_malloc.c:422)
==19855== by 0x2068B2BA: ROOT::Fit::Chi2FCN<ROOT::Math::IBaseFunctionMultiDimTempl, ROOT::Math::IParametricFunctionMultiDimTempl >::Clone() const (Chi2FCN.h:112)
==19855== by 0x20656C89: ROOT::Math::BasicMinimizer::SetFunction(ROOT::Math::IBaseFunctionMultiDimTempl const&) (BasicMinimizer.cxx:243)
==19855== by 0x26A2F845: ROOT::Math::GSLNLSMinimizer::SetFunction(ROOT::Math::IBaseFunctionMultiDimTempl const&) (GSLNLSMinimizer.cxx:174)
==19855== by 0x206841C4: ROOT::Fit::Fitter::DoInitMinimizer() (Fitter.cxx:857)
==19855== by 0x20684DAE: ROOT::Fit::Fitter::FitFCN() (Fitter.cxx:338)

Hi,
Thank you for reporting the problem. I have now identified the leak, I will put a PR fixing the problem

Best regards

Lorenzo

Hi Lorenzo,

Thank you for identifying the leak and putting in a PR. Would it be possible for you to provide me a link to the PR so I can track its progress?

Thanks!

Hi,
Here is the PR: [Math] Fix memory leak when using GSLMultiFit and improve Fitter class by lmoneta · Pull Request #10439 · root-project/root · GitHub

Cheers

Lorenzo