From 167b08bfbbfc9efcf709e8037eae4b7cc1148c59 Mon Sep 17 00:00:00 2001 From: Scott R Charlton Date: Tue, 15 Jul 2014 03:36:38 +0000 Subject: [PATCH] fixes valgrind memory leaks that occured when error/RF_error was called within a block containing implicit dtors; seems that R uses setjmp/longjmp to handle errors which produces undefined behavior under g++ see http://stackoverflow.com/questions/1376085/c-safe-to-use-longjmp-and-setjmp git-svn-id: svn://136.177.114.72/svn_GW/IPhreeqc/trunk@8843 1feff8c3-07ed-0310-ac33-dd36852eb9cd --- R/R.cpp | 59 ++++++++++++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/R/R.cpp b/R/R.cpp index 7a1fc0f9..4680317c 100644 --- a/R/R.cpp +++ b/R/R.cpp @@ -14,6 +14,10 @@ public: static IPhreeqc instance; return instance; } + static std::string& err_str() { + static std::string instance; + return instance; + } }; @@ -33,9 +37,7 @@ accumLine(SEXP line) if (STRING_ELT(line, 0) != NA_STRING) { str_in = CHAR(STRING_ELT(line, 0)); if (R::singleton().AccumulateLine(str_in) != VR_OK) { - std::ostringstream oss; - oss << R::singleton().GetErrorString(); - error(oss.str().c_str()); + error(R::singleton().GetErrorString()); } } @@ -53,15 +55,13 @@ accumLineLst(SEXP line) } int n = length(line); - std::ostringstream oss; + //std::ostringstream oss; for (int i = 0; i < n; ++i) { if (STRING_ELT(line, i) != NA_STRING) { str_in = CHAR(STRING_ELT(line, 0)); if (R::singleton().AccumulateLine(str_in) != VR_OK) { - std::ostringstream err; - err << R::singleton().GetErrorString(); - error(err.str().c_str()); + error(R::singleton().GetErrorString()); } } } @@ -733,9 +733,7 @@ loadDB(SEXP filename) name = CHAR(STRING_ELT(filename, 0)); if (R::singleton().LoadDatabase(name) != VR_OK) { - std::ostringstream err; - err << R::singleton().GetErrorString(); - error(err.str().c_str()); + error(R::singleton().GetErrorString()); } return(R_NilValue); @@ -750,20 +748,21 @@ loadDBLst(SEXP input) } int n = length(input); - std::ostringstream oss; + std::ostringstream *poss = new std::ostringstream(); for (int i = 0; i < n; ++i) { if (STRING_ELT(input, i) != NA_STRING) { - oss << CHAR(STRING_ELT(input, i)) << "\n"; + (*poss) << CHAR(STRING_ELT(input, i)) << "\n"; } } - if (R::singleton().LoadDatabaseString(oss.str().c_str()) != VR_OK) { - std::ostringstream err; - err << R::singleton().GetErrorString(); - error(err.str().c_str()); + if (R::singleton().LoadDatabaseString((*poss).str().c_str()) != VR_OK) { + // all dtors must be called before error + delete poss; + error(R::singleton().GetErrorString()); } + delete poss; return(R_NilValue); } @@ -780,9 +779,7 @@ loadDBStr(SEXP input) string = CHAR(STRING_ELT(input, 0)); if (R::singleton().LoadDatabaseString(string) != VR_OK) { - std::ostringstream err; - err << R::singleton().GetErrorString(); - error(err.str().c_str()); + error(R::singleton().GetErrorString()); } return(R_NilValue); @@ -792,9 +789,7 @@ SEXP runAccum(void) { if (R::singleton().RunAccumulated() != VR_OK) { - std::ostringstream oss; - oss << R::singleton().GetErrorString(); - error(oss.str().c_str()); + error(R::singleton().GetErrorString()); } return(R_NilValue); } @@ -811,9 +806,7 @@ runFile(SEXP filename) name = CHAR(STRING_ELT(filename, 0)); if (R::singleton().RunFile(name) != VR_OK) { - std::ostringstream oss; - oss << R::singleton().GetErrorString(); - error(oss.str().c_str()); + error(R::singleton().GetErrorString()); } return(R_NilValue); @@ -831,9 +824,7 @@ runString(SEXP input) in = CHAR(STRING_ELT(input, 0)); if (R::singleton().RunString(in) != VR_OK) { - std::ostringstream oss; - oss << R::singleton().GetErrorString(); - error(oss.str().c_str()); + error(R::singleton().GetErrorString()); } return(R_NilValue); @@ -848,20 +839,20 @@ runStringLst(SEXP input) } int n = length(input); - std::ostringstream oss; + std::ostringstream *poss = new std::ostringstream(); for (int i = 0; i < n; ++i) { if (STRING_ELT(input, i) != NA_STRING) { - oss << CHAR(STRING_ELT(input, i)) << "\n"; + (*poss) << CHAR(STRING_ELT(input, i)) << "\n"; } } - if (R::singleton().RunString(oss.str().c_str()) != VR_OK) { - std::ostringstream err; - err << R::singleton().GetErrorString(); - error(err.str().c_str()); + if (R::singleton().RunString((*poss).str().c_str()) != VR_OK) { + delete poss; + error(R::singleton().GetErrorString()); } + delete poss; return(R_NilValue); }