From 44a0938c631a1e05357018eaeff49082b112fed6 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Thu, 24 Oct 2024 12:43:50 -0700 Subject: [PATCH] fix: resolve memory leaks in auto2000 plugin (plus lm and NelderMead plugins) - Identified and corrected memory leaks in using RRStringArrayPtr, RRCDataPtr, and RRVectorPtr. - Implemented unique_ptr for RRVector. --- .../telAutoTelluriumInterface.cpp | 62 ++++++++++++++++--- rrplugins/plugins/auto2000/telAutoWorker.cpp | 9 +++ rrplugins/plugins/levenberg_marquardt/lm.cpp | 6 +- .../plugins/nelder_mead/nmNelderMead.cpp | 6 +- wrappers/C/rrc_cpp_support.cpp | 14 ++--- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/rrplugins/plugins/auto2000/libAutoTelluriumInterface/telAutoTelluriumInterface.cpp b/rrplugins/plugins/auto2000/libAutoTelluriumInterface/telAutoTelluriumInterface.cpp index 82fecbfe89..3c65cb745a 100644 --- a/rrplugins/plugins/auto2000/libAutoTelluriumInterface/telAutoTelluriumInterface.cpp +++ b/rrplugins/plugins/auto2000/libAutoTelluriumInterface/telAutoTelluriumInterface.cpp @@ -112,8 +112,28 @@ void AutoTellurimInterface::setInitialPCPValue() if(mAutoConstants.PreSimulation) { // Two simulations gives better results. - gHostInterface->simulateEx(mRR, mAutoConstants.PreSimulationStart, mAutoConstants.PreSimulationDuration, mAutoConstants.PreSimulationSteps); - gHostInterface->simulateEx(mRR, mAutoConstants.PreSimulationStart, mAutoConstants.PreSimulationDuration, mAutoConstants.PreSimulationSteps); + rrc::RRCDataPtr simulationData = gHostInterface->simulateEx(mRR, mAutoConstants.PreSimulationStart, mAutoConstants.PreSimulationDuration, mAutoConstants.PreSimulationSteps); + if (simulationData != NULL) { + delete[] simulationData->Weights; + if (simulationData->ColumnHeaders != NULL) { + for (int i = 0; i < simulationData->CSize; i++) + delete[] simulationData->ColumnHeaders[i]; + delete[] simulationData->ColumnHeaders; + } + delete[] simulationData->Data; + delete simulationData; + } + simulationData = gHostInterface->simulateEx(mRR, mAutoConstants.PreSimulationStart, mAutoConstants.PreSimulationDuration, mAutoConstants.PreSimulationSteps); + if (simulationData != NULL) { + delete[] simulationData->Weights; + if (simulationData->ColumnHeaders != NULL) { + for (int i = 0; i < simulationData->CSize; i++) + delete[] simulationData->ColumnHeaders[i]; + delete[] simulationData->ColumnHeaders; + } + delete[] simulationData->Data; + delete simulationData; + } } double* val= new double; //just to make the call compatible else no use @@ -147,12 +167,22 @@ bool AutoTellurimInterface::setupUsingCurrentModel() rrc::RRStringArrayPtr lists= gHostInterface->getGlobalParameterIds(mRR); StringList list1(lists->String,lists->Count); mModelParameters = list1; + for (int i = 0; i < lists->Count; i++) { + delete[] lists->String[i]; + } + delete[] lists->String; + delete lists; lists= gHostInterface->getBoundarySpeciesIds(mRR); if (lists) { StringList list2(lists->String, lists->Count); //Boundary species can be used as PCP as well mModelBoundarySpecies = list2; + for (int i = 0; i < lists->Count; i++) { + delete[] lists->String[i]; + } + delete[] lists->String; + delete lists; } //Set initial value of Primary continuation parameter setInitialPCPValue(); @@ -223,17 +253,24 @@ int autoCallConv AutoTellurimInterface::ModelInitializationCallback(long ndim, d } int nrIndFloatingSpecies = gHostInterface->_getNumIndFloatingSpecies(mRR)+gHostInterface->_getNumRateRules(mRR); - double* floatCon = new double[nrIndFloatingSpecies]; - - floatCon = (gHostInterface->getFloatingSpeciesConcentrations(mRR))->Data; + rrc::RRVectorPtr floatCon = (gHostInterface->getFloatingSpeciesConcentrations(mRR)); int nMin = min(nrIndFloatingSpecies, ndim); for(int i = 0; i < nMin; i++) { - u[i] = floatCon[i]; + u[i] = floatCon->Data[i]; } - delete[] floatCon; + if (floatCon != NULL) { + if (floatCon->Data != NULL) { + delete[] floatCon->Data; + floatCon->Data = NULL; + } + + delete floatCon; + floatCon = NULL; + } + return 0; } @@ -284,6 +321,13 @@ void autoCallConv AutoTellurimInterface::ModelFunctionCallback(const double* oVa rrc::RRStringArrayPtr temp= gHostInterface->getSteadyStateSelectionList(mRR); tlp::StringList selRecs(temp->String, temp->Count); + if (temp->String) { + for (int i = 0; i < temp->Count; i++) { + delete[] temp->String[i]; + } + delete[] temp->String; + } + delete temp; tlp::StringList selList = selRecs; vector variableTemp(selList.size()); @@ -314,10 +358,10 @@ void autoCallConv AutoTellurimInterface::ModelFunctionCallback(const double* oVa } } - rrc::RRVectorPtr intermediate= new rrc::RRVector; + std::unique_ptr intermediate = std::make_unique(); intermediate->Count = numIndFloatingSpecies; intermediate->Data = tempConc; - gHostInterface->setFloatingSpeciesConcentrations(mRR, intermediate); + gHostInterface->setFloatingSpeciesConcentrations(mRR, intermediate.get()); delete [] tempConc; diff --git a/rrplugins/plugins/auto2000/telAutoWorker.cpp b/rrplugins/plugins/auto2000/telAutoWorker.cpp index 3dd12f0583..23ef2b4ced 100644 --- a/rrplugins/plugins/auto2000/telAutoWorker.cpp +++ b/rrplugins/plugins/auto2000/telAutoWorker.cpp @@ -124,6 +124,15 @@ void AutoWorker::run() rrc::RRStringArrayPtr temp = gHostInterface->getSteadyStateSelectionList(mTheHost.rrHandle); StringList selRecs (temp->String, temp->Count); StringList selList = selRecs; + if (temp != NULL) { + if (temp->String != NULL) { + for (int i = 0; i < temp->Count; i++) { + delete[] temp->String[i]; + } + delete[] temp->String; + } + delete temp; + } TelluriumData& data = mTheHost.mBifurcationData.getValueReference(); diff --git a/rrplugins/plugins/levenberg_marquardt/lm.cpp b/rrplugins/plugins/levenberg_marquardt/lm.cpp index 92ba46015c..a3fff694c2 100644 --- a/rrplugins/plugins/levenberg_marquardt/lm.cpp +++ b/rrplugins/plugins/levenberg_marquardt/lm.cpp @@ -97,8 +97,10 @@ namespace lmfit mProperties.add(&mStatusMessage); //Allocate model and Residuals data - mResidualsData.setValue(new TelluriumData()); - mModelData.setValue(new TelluriumData()); + TelluriumData residualsData; + mResidualsData.setValue(&residualsData); + TelluriumData modelData; + mModelData.setValue(&modelData); mHint = "Parameter fitting using the Levenberg-Marquardt algorithm"; mDescription = "The Levenberg-Marquardt plugin is used to fit a proposed \ diff --git a/rrplugins/plugins/nelder_mead/nmNelderMead.cpp b/rrplugins/plugins/nelder_mead/nmNelderMead.cpp index deda9dd342..7503b64821 100644 --- a/rrplugins/plugins/nelder_mead/nmNelderMead.cpp +++ b/rrplugins/plugins/nelder_mead/nmNelderMead.cpp @@ -92,8 +92,10 @@ namespace nmfit mProperties.add(&mStatusMessage); //Allocate model and Residuals data - mResidualsData.setValue(new TelluriumData()); - mModelData.setValue(new TelluriumData()); + TelluriumData residualsData; + mResidualsData.setValue(&residualsData); + TelluriumData modelData; + mModelData.setValue(&modelData); mHint = "Parameter fitting using the Nelder-Mead algorithm"; mDescription = "The Nelder-Mead plugin is used to fit a proposed \ diff --git a/wrappers/C/rrc_cpp_support.cpp b/wrappers/C/rrc_cpp_support.cpp index 20aafd9510..3674f83fe1 100644 --- a/wrappers/C/rrc_cpp_support.cpp +++ b/wrappers/C/rrc_cpp_support.cpp @@ -209,15 +209,15 @@ RRStringArrayPtr createList(const rrc::StringList& sList) RRStringArray* list = new RRStringArray; list->Count = sList.Count(); - if (list->Count) - list->String = new char*[list->Count]; + if (list->Count) { + list->String = new char *[list->Count]; + for(int i = 0; i < list->Count; i++) + { + list->String[i] = rr::createText(sList[i]); + } + } else list->String = NULL; - - for(int i = 0; i < list->Count; i++) - { - list->String[i] = rr::createText(sList[i]); - } return list; }