From 66aa847b58bc45264c242c895fb5e778878be384 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sat, 6 Jun 2026 15:38:15 +0200 Subject: [PATCH] PFitter: replace TObjArray/TObjString with PStringUtils Replace ROOT's TString::Tokenize() + TObjArray/TObjString token handling with the dependency-free PStringUtils::Split() across all command/theory parsing in PFitter (GetPhaseParams, GetParFromFun, CheckCommands and the Execute* helpers). Split() mirrors Tokenize() semantics (delimiter-set, skips empty tokens), so token counts and indices are unchanged. Each token is still copied into a TString, so the downstream Atoi/Atof/IsFloat/IsDigit/Contains/CompareTo logic stays as-is. Using a std::vector removes the manual TObjArray cleanup and incidentally fixes three pre-existing leaks: the tokens array in ExecuteFitRange was never freed, and the early return paths in ExecutePrintLevel and the SECTOR check in CheckCommands skipped the cleanup. Build of libPMusr and musrfit is clean; full ctest suite passes (85/85). Co-Authored-By: Claude Opus 4.8 --- src/classes/PFitter.cpp | 300 ++++++++-------------------------------- 1 file changed, 61 insertions(+), 239 deletions(-) diff --git a/src/classes/PFitter.cpp b/src/classes/PFitter.cpp index a25e1d69c..2d3394334 100644 --- a/src/classes/PFitter.cpp +++ b/src/classes/PFitter.cpp @@ -64,10 +64,9 @@ #include #include #include -#include -#include #include "PFitter.h" +#include "PStringUtils.h" //+++ PSectorChisq class +++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -397,8 +396,6 @@ void PFitter::GetPhaseParams() // default functions: // user functions cannot be checked! PMsrLines *theo = fRunInfo->GetMsrTheory(); - TObjArray *tok = nullptr; - TObjString *ostr = nullptr; TString str; int pos = -1; for (unsigned int i=0; isize(); i++) { @@ -423,18 +420,10 @@ void PFitter::GetPhaseParams() continue; // extract phase token - tok = line.Tokenize(" \t"); - if (tok == nullptr) { - std::cerr << "PFitter::GetPhaseParams(): **ERROR** couldn't tokenize theory line string." << std::endl; - return; + std::vector tok = PStringUtils::Split(line.Data(), " \t"); + if (static_cast(tok.size()) > pos) { + str = tok[pos].c_str(); } - if (tok->GetEntries() > pos) { - ostr = dynamic_cast(tok->At(pos)); - str = ostr->GetString(); - } - // clean up - delete tok; - tok = nullptr; // decode phase token. It can be funX, mapX, or a number if (str.Contains("fun")) { // function @@ -491,22 +480,15 @@ PIntVector PFitter::GetParFromFun(const TString funStr) PIntVector parVec; PMsrLines *funList = fRunInfo->GetMsrFunctions(); - TObjArray *tok = nullptr; - TObjString *ostr = nullptr; TString str; for (int i=0; isize(); i++) { if (funList->at(i).fLine.Contains(funStr)) { // tokenize function string - tok = funList->at(i).fLine.Tokenize(" =+-*/"); - if (tok == nullptr) { - std::cerr << "PFitter::GetParFromFun(): **ERROR** couldn't tokenize function string." << std::endl; - return parVec; - } + std::vector tok = PStringUtils::Split(funList->at(i).fLine.Data(), " =+-*/"); - for (int j=1; jGetEntries(); j++) { - ostr = dynamic_cast(tok->At(j)); - str = ostr->GetString(); + for (int j=1; j(tok.size()); j++) { + str = tok[j].c_str(); // parse tok for parX if (str.Contains("par")) { // find start idx of par in token @@ -533,10 +515,6 @@ PIntVector PFitter::GetParFromFun(const TString funStr) } } } - - // clean up - delete tok; - tok = nullptr; } } @@ -996,16 +974,14 @@ Bool_t PFitter::CheckCommands() cmd.second = cmdLineNo; fCmdList.push_back(cmd); // filter out possible parameters for scan - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; UInt_t ival; - tokens = line.Tokenize(", \t"); + tokens = PStringUtils::Split(line.Data(), ", \t"); - for (Int_t i=0; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=0; i(tokens.size()); i++) { + str = tokens[i].c_str(); if ((i==1) || (i==2)) { // parX / parY // check that token is a UInt_t @@ -1016,10 +992,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } ival = str.Atoi(); @@ -1031,10 +1003,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } // keep parameter @@ -1051,10 +1019,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } ival = str.Atoi(); @@ -1065,20 +1029,12 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } fScanNoPoints = ival; } } - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("EIGEN", TString::kIgnoreCase)) { cmd.first = PMN_EIGEN; cmd.second = cmdLineNo; @@ -1090,15 +1046,13 @@ Bool_t PFitter::CheckCommands() // (iii) FIT_RANGE start1 end1 start2 end2 ... startN endN // (iv) FIT_RANGE fgb+n0 lgb-n1 // (v) FIT_RANGE fgb+n00 lgb-n01 fgb+n10 lgb-n11 ... fgb+nN0 lgb-nN1 - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = line.Tokenize(", \t"); + tokens = PStringUtils::Split(line.Data(), ", \t"); - if (tokens->GetEntries() == 2) { // should only be RESET - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); + if (static_cast(tokens.size()) == 2) { // should only be RESET + str = tokens[1].c_str(); if (str.Contains("RESET", TString::kIgnoreCase)) { cmd.first = PMN_FIT_RANGE; cmd.second = cmdLineNo; @@ -1110,32 +1064,23 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> with N the number of runs in the msr-file." << std::endl; std::cerr << std::endl << ">> Found " << str.Data() << ", instead of RESET" << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } - } else if ((tokens->GetEntries() > 1) && (static_cast(tokens->GetEntries()) % 2) == 1) { - if ((tokens->GetEntries() > 3) && ((static_cast(tokens->GetEntries())-1)) != 2*fRunInfo->GetMsrRunList()->size()) { + } else if ((static_cast(tokens.size()) > 1) && (static_cast(static_cast(tokens.size())) % 2) == 1) { + if ((static_cast(tokens.size()) > 3) && ((static_cast(static_cast(tokens.size()))-1)) != 2*fRunInfo->GetMsrRunList()->size()) { std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo; std::cerr << std::endl << ">> " << line.Data(); std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE | FIT_RANGE .. |"; std::cerr << std::endl << ">> FIT_RANGE fgb+ lgb- | FIT_RANGE fgb+ lgb- fgb+ lgb- ... fgb+ lgb-,"; std::cerr << std::endl << ">> with N the number of runs in the msr-file."; - std::cerr << std::endl << ">> Found N=" << (tokens->GetEntries()-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl; + std::cerr << std::endl << ">> Found N=" << (static_cast(tokens.size())-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } else { // check that all range entries are numbers or fgb+n0 / lgb-n1 Bool_t ok = true; - for (Int_t n=1; nGetEntries(); n++) { - ostr = dynamic_cast(tokens->At(n)); - str = ostr->GetString(); + for (Int_t n=1; n(tokens.size()); n++) { + str = tokens[n].c_str(); if (!str.IsFloat()) { if ((n%2 == 1) && (!str.Contains("fgb", TString::kIgnoreCase))) ok = false; @@ -1158,10 +1103,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> with N the number of runs in the msr-file."; std::cerr << std::endl << ">> Found token '" << str.Data() << "', which is not a floating point number." << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } } @@ -1172,29 +1113,19 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> FIT_RANGE fgb+ lgb- | FIT_RANGE fgb+ lgb- fgb+ lgb- ... fgb+ lgb-,"; std::cerr << std::endl << ">> with N the number of runs in the msr-file."; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("FIX", TString::kIgnoreCase)) { // check if the given set of parameters (number or names) is present - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; UInt_t ival; - tokens = line.Tokenize(", \t"); + tokens = PStringUtils::Split(line.Data(), ", \t"); - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=1; i(tokens.size()); i++) { + str = tokens[i].c_str(); if (str.IsDigit()) { // token might be a parameter number ival = str.Atoi(); @@ -1205,10 +1136,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } } else { // token might be a parameter name @@ -1226,19 +1153,11 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } } } - if (tokens) { - delete tokens; - tokens = nullptr; - } // everything looks fine, feed the command list cmd.first = PMN_FIX; @@ -1278,16 +1197,14 @@ Bool_t PFitter::CheckCommands() fCmdList.push_back(cmd); } else if (line.Contains("RELEASE", TString::kIgnoreCase)) { // check if the given set of parameters (number or names) is present - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; UInt_t ival; - tokens = line.Tokenize(", \t"); + tokens = PStringUtils::Split(line.Data(), ", \t"); - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=1; i(tokens.size()); i++) { + str = tokens[i].c_str(); if (str.IsDigit()) { // token might be a parameter number ival = str.Atoi(); @@ -1298,10 +1215,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } } else { // token might be a parameter name @@ -1319,19 +1232,11 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } } } - if (tokens) { - delete tokens; - tokens = nullptr; - } cmd.first = PMN_RELEASE; cmd.second = cmdLineNo; fCmdList.push_back(cmd); @@ -1348,16 +1253,14 @@ Bool_t PFitter::CheckCommands() cmd.second = cmdLineNo; fCmdList.push_back(cmd); // filter out possible parameters for scan - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; UInt_t ival; - tokens = line.Tokenize(", \t"); + tokens = PStringUtils::Split(line.Data(), ", \t"); - for (Int_t i=0; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=0; i(tokens.size()); i++) { + str = tokens[i].c_str(); if (i==1) { // get parameter number // check that token is a UInt_t if (!str.IsDigit()) { @@ -1367,10 +1270,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } ival = str.Atoi(); @@ -1382,10 +1281,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } // keep parameter @@ -1402,10 +1297,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } ival = str.Atoi(); @@ -1416,10 +1307,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } fScanNoPoints = ival; @@ -1434,10 +1321,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } fScanLow = str.Atof(); @@ -1452,33 +1335,23 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]"; std::cerr << std::endl; fIsValid = false; - if (tokens) { - delete tokens; - tokens = nullptr; - } break; } fScanHigh = str.Atof(); } } - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("SIMPLEX", TString::kIgnoreCase)) { cmd.first = PMN_SIMPLEX; cmd.second = cmdLineNo; fCmdList.push_back(cmd); } else if (line.Contains("STRATEGY", TString::kIgnoreCase)) { - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = line.Tokenize(" \t"); - if (tokens->GetEntries() == 2) { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); + tokens = PStringUtils::Split(line.Data(), " \t"); + if (static_cast(tokens.size()) == 2) { + str = tokens[1].c_str(); if (str.CompareTo("0") == 0) { // low fStrategy = 0; } else if (str.CompareTo("1") == 0) { // default @@ -1494,10 +1367,6 @@ Bool_t PFitter::CheckCommands() } } - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("USER_COVARIANCE", TString::kIgnoreCase)) { cmd.first = PMN_USER_COVARIANCE; cmd.second = cmdLineNo; @@ -1513,35 +1382,28 @@ Bool_t PFitter::CheckCommands() fCmdList.push_back(cmd); // check if the given sector arguments are valid time stamps, i.e. doubles and value < lgb time stamp - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = line.Tokenize(" ,\t"); + tokens = PStringUtils::Split(line.Data(), " ,\t"); - if (tokens->GetEntries() == 1) { // no sector time stamps given -> issue an error + if (static_cast(tokens.size()) == 1) { // no sector time stamps given -> issue an error std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo; std::cerr << std::endl << ">> " << line.Data(); std::cerr << std::endl << ">> At least one sector time stamp is expected."; std::cerr << std::endl << ">> Will stop ..."; std::cerr << std::endl; - // cleanup - if (tokens) { - delete tokens; - tokens = nullptr; - } fIsValid = false; fSectorFlag = false; break; } Double_t dval; - for (Int_t i=1; iGetEntries(); i++) { + for (Int_t i=1; i(tokens.size()); i++) { // keep time range of sector PSectorChisq sec(fRunInfo->GetNoOfRuns()); // get parse tokens - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + str = tokens[i].c_str(); if (str.IsFloat()) { dval = str.Atof(); // check that the sector time stamp is smaller than all lgb time stamps @@ -1552,11 +1414,6 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> The sector time stamp " << dval << " is > as the lgb time stamp (" << fOriginalFitRange[j].second << ") of run " << j << "."; std::cerr << std::endl << ">> Will stop ..."; std::cerr << std::endl; - // cleanup - if (tokens) { - delete tokens; - tokens = nullptr; - } fIsValid = false; fSectorFlag = false; return fIsValid; @@ -1571,21 +1428,12 @@ Bool_t PFitter::CheckCommands() std::cerr << std::endl << ">> The sector time stamp '" << str << "' is not a number."; std::cerr << std::endl << ">> Will stop ..."; std::cerr << std::endl; - // cleanup - if (tokens) { - delete tokens; - tokens = nullptr; - } fIsValid = false; fSectorFlag = false; break; } } - if (tokens) { - delete tokens; - tokens = nullptr; - } } else { // unkown command std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo << " an unkown command is found:"; std::cerr << std::endl << ">> " << line.Data(); @@ -1729,27 +1577,24 @@ Bool_t PFitter::ExecuteFitRange(UInt_t lineNo) return true; } - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = fCmdLines[lineNo].fLine.Tokenize(", \t"); + tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t"); PMsrRunList *runList = fRunInfo->GetMsrRunList(); // execute command, no error checking needed since this has been already carried out in CheckCommands() - if (tokens->GetEntries() == 2) { // reset command + if (static_cast(tokens.size()) == 2) { // reset command fRunListCollection->SetFitRange(fOriginalFitRange); - } else if (tokens->GetEntries() == 3) { // single fit range for all runs + } else if (static_cast(tokens.size()) == 3) { // single fit range for all runs Double_t start = 0.0, end = 0.0; PDoublePair fitRange; PDoublePairVector fitRangeVector; - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); + str = tokens[1].c_str(); start = str.Atof(); - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); + str = tokens[2].c_str(); end = str.Atof(); fitRange.first = start; @@ -1763,11 +1608,9 @@ Bool_t PFitter::ExecuteFitRange(UInt_t lineNo) PDoublePairVector fitRangeVector; for (UInt_t i=0; isize(); i++) { - ostr = dynamic_cast(tokens->At(2*i+1)); - str = ostr->GetString(); + str = tokens[2*i+1].c_str(); start = str.Atof(); - ostr = dynamic_cast(tokens->At(2*i+2)); - str = ostr->GetString(); + str = tokens[2*i+2].c_str(); end = str.Atof(); fitRange.first = start; @@ -1795,15 +1638,13 @@ Bool_t PFitter::ExecuteFix(UInt_t lineNo) { std::cout << ">> PFitter::ExecuteFix(): " << fCmdLines[lineNo].fLine.Data() << std::endl; - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = fCmdLines[lineNo].fLine.Tokenize(", \t"); + tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t"); - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=1; i(tokens.size()); i++) { + str = tokens[i].c_str(); if (str.IsDigit()) { // token is a parameter number fMnUserParams.Fix(static_cast(str.Atoi())-1); @@ -1812,11 +1653,6 @@ Bool_t PFitter::ExecuteFix(UInt_t lineNo) } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } return true; } @@ -2124,19 +1960,17 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo) { std::cout << ">> PFitter::ExecutePrintLevel(): " << fCmdLines[lineNo].fLine.Data() << std::endl; - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = fCmdLines[lineNo].fLine.Tokenize(", \t"); + tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t"); - if (tokens->GetEntries() < 2) { + if (static_cast(tokens.size()) < 2) { std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL , where =0-3" << std::endl << std::endl; return false; } - ostr = (TObjString*)tokens->At(1); - str = ostr->GetString(); + str = tokens[1].c_str(); Int_t ival; if (str.IsDigit()) { @@ -2159,11 +1993,6 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo) ROOT::Minuit2::MnPrint::SetLevel(fPrintLevel); #endif - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } return true; } @@ -2180,17 +2009,15 @@ Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo) */ Bool_t PFitter::ExecuteRelease(UInt_t lineNo) { - TObjArray *tokens = nullptr; - TObjString *ostr; + std::vector tokens; TString str; - tokens = fCmdLines[lineNo].fLine.Tokenize(", \t"); + tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t"); std::cout << ">> PFitter::ExecuteRelease(): " << fCmdLines[lineNo].fLine.Data() << std::endl; - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); + for (Int_t i=1; i(tokens.size()); i++) { + str = tokens[i].c_str(); if (str.IsDigit()) { // token is a parameter number fMnUserParams.Release(static_cast(str.Atoi())-1); @@ -2203,11 +2030,6 @@ Bool_t PFitter::ExecuteRelease(UInt_t lineNo) } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } return true; }