Thanks to valgrind for spotting this. --- check/parser_memleak.cpp | 36 ++++++++++++++++++++++++++++++++++++ ginac/input_lexer.ll | 4 +++- 2 files changed, 39 insertions(+), 1 deletions(-) create mode 100644 check/parser_memleak.cpp diff --git a/check/parser_memleak.cpp b/check/parser_memleak.cpp new file mode 100644 index 0000000..f347ce9 --- /dev/null +++ b/check/parser_memleak.cpp @@ -0,0 +1,36 @@ +/** + * This small program exhibits the memory leak in the ginac_yylex(). + * Run it as + * + * valgrind --leak-check=yes ./parser_memleak + * + * or simply + * + * ulimit -v `expr 64 \* 1024` ./parser_memleak + */ +#include <iostream> +#include <stdexcept> +#include <ginac/ginac.h> +using namespace std; +using namespace GiNaC; + +int main(int argc, char** argv) { + const symbol x("x"), y("y"); + const lst syms(x, y); + // parser-generated symbol => memory leak. + static const char* str[] = { "x^2+2*x*y + cos(x)", "Li2(x/y) + log(y/x)" }; + + // depends on the amount of the available VM, compiler options, etc. + const unsigned N_max = 500000; + unsigned N=0; + ex e; + try { + for (; N < N_max; N++) { + e = ex(str[N & 1], syms); + } + } catch (std::bad_alloc) { + cerr << "N = " << N << endl; + return 1; + } + return 0; +} diff --git a/ginac/input_lexer.ll b/ginac/input_lexer.ll index f931394..bc568ce 100644 --- a/ginac/input_lexer.ll +++ b/ginac/input_lexer.ll @@ -119,7 +119,9 @@ Digits ginac_yylval = (long)Digits; return T_DIGITS; {A}{AN}* { sym_tab::const_iterator i = syms.find(yytext); if (i == syms.end()) { - syms[yytext] = sym_def(ginac_yylval = *(new symbol(yytext)), false); + symbol tmp(yytext); + ginac_yylval = tmp; + syms[yytext] = sym_def(tmp, false); } else ginac_yylval = (*i).second.sym; return T_SYMBOL; -- 1.5.3.2 Best regards, Alexei -- All science is either physics or stamp collecting.