[PATCH] Fix memory leaks in mul::eval() and power::eval() (GiNaC 1.4, HEAD)
The bug was introduced by the patch commit f418c6ee4d558c852e1fb95533af07a3ae43f409 Author: Alexei Sheplyakov <varg@theor.jinr.ru> Date: Wed Jul 11 14:34:42 2007 +0400 (it was commited into the official branch as commit a602d34c225dceb3e53742a7b3e19a4b5e280485 Author: Jens Vollinga <vollinga@thep.physik.uni-mainz.de> Date: Wed Jul 11 21:07:40 2007 +0000) While at it, delete bogus try -- catch block in the ex::series(), since it papers over some serious issues (like this one) and does not seem to do anything useful. Thanks to valgrind (http://valgrind.kde.org) developers for a wonderful piece of software. Debugging this problem would take way too long without it. --- check/mul_eval_memleak.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++++ ginac/mul.cpp | 4 +- ginac/power.cpp | 4 +- ginac/pseries.cpp | 6 +-- 4 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 check/mul_eval_memleak.cpp diff --git a/check/mul_eval_memleak.cpp b/check/mul_eval_memleak.cpp new file mode 100644 index 0000000..78e9312 --- /dev/null +++ b/check/mul_eval_memleak.cpp @@ -0,0 +1,119 @@ +/** + * @file mul_eval_memleak.cpp Test for memory leak in {mul,power}::eval + * + * The bug was introduced by + * + * commit f418c6ee4d558c852e1fb95533af07a3ae43f409 + * Author: Alexei Sheplyakov <varg@theor.jinr.ru> + * Date: Wed Jul 11 14:34:42 2007 +0400 + * (it was commited into the official branch as + * commit a602d34c225dceb3e53742a7b3e19a4b5e280485 + * Author: Jens Vollinga <vollinga@thep.physik.uni-mainz.de> + * Date: Wed Jul 11 21:07:40 2007 +0000) + */ + +/* + * GiNaC Copyright (C) 1999-2007 Johannes Gutenberg University Mainz, Germany + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <iostream> +#include <ginac/ginac.h> +#include <string> +#include <stdexcept> +using namespace std; +using namespace GiNaC; + +const unsigned check_mul_eval_memleak(const unsigned N) +{ + // Expanding this expression into a Laurent series triggers the bug. + static const string e_str("\ +1/605927415293858601*tgamma(3-eps)^(-1)*tgamma(2-eps)*(5013234896802\ +*(-1+2*eps)*((-2539001/2)*eps^(-2)+(-7617003/2+1692800*log(920*scale\ +^(-1))+3385202*log(1301*scale^(-1)))*eps^(-1)+F)+(846400+2539001*eps\ +)*(2539001*(-1+2*eps)*((-2539001/2)*eps^(-2)+(-7617003/2+1692800*log\ +(920*scale^(-1))+3385202*log(1301*scale^(-1)))*eps^(-1)+F)+286523497\ +2800*(-1+eps)^(-1)*eps^(-2)*(920*scale^(-1))^(-2*eps)*(1301*scale^(-\ +1))^(-2*eps)*tgamma(1+eps)^2)+6061411748045832000*(-1+eps)^(-1)*eps^\ +(-2)*(920*scale^(-1))^(-2*eps)*(1301*scale^(-1))^(-2*eps)*tgamma(1+e\ +ps)^2+716056132401*((-2539001/2)*eps^(-2)+(-7617003/2+1692800*log(92\ +0*scale^(-1))+3385202*log(1301*scale^(-1)))*eps^(-1)+F))+71656139360\ +0/716056132401*tgamma(1-eps)*tgamma(2*eps)^(-1)*tgamma(eps)^2*tgamma\ +(3-eps)^(-1)*(920*scale^(-1))^(-4*eps)*tgamma(-1+2*eps)-2/6059274152\ +93858601*tgamma(3-eps)^(-1)*(2149010446400*(-1+2*eps)*((-2539001/2)*\ +eps^(-2)+(-7617003/2+1692800*log(920*scale^(-1))+3385202*log(1301*sc\ +ale^(-1)))*eps^(-1)+F)+2425134880977920000*(-1+eps)^(-1)*eps^(-2)*(9\ +20*scale^(-1))^(-2*eps)*(1301*scale^(-1))^(-2*eps)*tgamma(1+eps)^2-7\ +16056132401*((-2539001/2)*eps^(-2)+(-7617003/2+1692800*log(920*scale\ +^(-1))+3385202*log(1301*scale^(-1)))*eps^(-1)+F)+1692601*(-1+2*eps)*\ +(2539001*(-1+2*eps)*((-2539001/2)*eps^(-2)+(-7617003/2+1692800*log(9\ +20*scale^(-1))+3385202*log(1301*scale^(-1)))*eps^(-1)+F)+28652349728\ +00*(-1+eps)^(-1)*eps^(-2)*(920*scale^(-1))^(-2*eps)*(1301*scale^(-1)\ +)^(-2*eps)*tgamma(1+eps)^2))*tgamma(2-eps)+(1/716056132401*I)*tgamma\ +(-1+eps)*mb^2*(mb*scale^(-1))^(-2*eps)*((716392960000*I)*mb^(-2)*(92\ +0*scale^(-1))^(-2*eps)*tgamma(-2+eps)-(2864898145201*I)*mb^(-2)*(130\ +1*scale^(-1))^(-2*eps)*tgamma(-2+eps)-(716224526400*I)*tgamma(-1+eps\ +)*mb^(-2)*(920*scale^(-1))^(-2*eps))-3385202/605927415293858601*tgam\ +ma(3-eps)^(-1)*tgamma(2-eps)*(2539001*(-1+2*eps)*((-2539001/2)*eps^(\ +-2)+(-7617003/2+1692800*log(920*scale^(-1))+3385202*log(1301*scale^(\ +-1)))*eps^(-1)+F)+2865234972800*(-1+eps)^(-1)*eps^(-2)*(920*scale^(-\ +1))^(-2*eps)*(1301*scale^(-1))^(-2*eps)*tgamma(1+eps)^2+846201*((-25\ +39001/2)*eps^(-2)+(-7617003/2+1692800*log(920*scale^(-1))+3385202*lo\ +g(1301*scale^(-1)))*eps^(-1)+F))\ +"); + const symbol eps("eps"), scale("scale"), mb("mb"), F("F"); + const lst syms(eps, scale, mb, F); + const ex e0(e_str, syms); + + unsigned i = 0; + unsigned n_failures = 0; + + ex e; + try { + for (; i < N; i++) + e = e0.series(eps, 1).subs(Euler==0).expand(); + } catch (std::bad_alloc) { + return i; + } + return 0; +} + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <unistd.h> + +static void set_VM_limit(const unsigned long MB) { + const unsigned mem_lim_kb = MB*1024*1024; + struct rlimit lim; + lim.rlim_cur = mem_lim_kb; + lim.rlim_max = mem_lim_kb; + setrlimit(RLIMIT_AS, &lim); +} + +int main(int argc, char** argv) { + static const unsigned max_mem = 32; // megabytes + // otherwise one need wait for a long[er] time. + set_VM_limit(max_mem); + static const unsigned n_of_tests = 10000; + const unsigned n_loops = check_mul_eval_memleak(n_of_tests); + if (n_loops) { + cerr << "memory exhausted after " << n_loops << " loops" << endl; + return 1; + } + return 0; +} + diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 4e95a63..9e1ba48 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -469,8 +469,8 @@ ex mul::eval(int level) const // XXX: What is the best way to check if the polynomial is a primitive? numeric c = i->rest.integer_content(); - const numeric& lead_coeff = - ex_to<numeric>(ex_to<add>(i->rest).seq.begin()->coeff).div_dyn(c); + const numeric lead_coeff = + ex_to<numeric>(ex_to<add>(i->rest).seq.begin()->coeff).div(c); const bool canonicalizable = lead_coeff.is_integer(); // XXX: The main variable is chosen in a random way, so this code diff --git a/ginac/power.cpp b/ginac/power.cpp index 7d909e8..cbf196f 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -505,8 +505,8 @@ ex power::eval(int level) const // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4) if (num_exponent->is_integer() && is_exactly_a<add>(ebasis)) { numeric icont = ebasis.integer_content(); - const numeric& lead_coeff = - ex_to<numeric>(ex_to<add>(ebasis).seq.begin()->coeff).div_dyn(icont); + const numeric lead_coeff = + ex_to<numeric>(ex_to<add>(ebasis).seq.begin()->coeff).div(icont); const bool canonicalizable = lead_coeff.is_integer(); const bool unit_normal = lead_coeff.is_pos_integer(); diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 0da6ae8..f4571ed 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -1280,11 +1280,7 @@ ex ex::series(const ex & r, int order, unsigned options) const else throw (std::logic_error("ex::series(): expansion point has unknown type")); - try { - e = bp->series(rel_, order, options); - } catch (std::exception &x) { - throw (std::logic_error(std::string("unable to compute series (") + x.what() + ")")); - } + e = bp->series(rel_, order, options); return e; } -- 1.5.3.2 -- All science is either physics or stamp collecting.
participants (1)
-
Alexei Sheplyakov