[GiNaC-devel] [PATCH] Fix memory leaks in mul::eval() and power::eval() (GiNaC 1.4, HEAD)

Alexei Sheplyakov varg at theor.jinr.ru
Sat Nov 17 17:36:10 CET 2007


The bug was introduced by the patch

commit f418c6ee4d558c852e1fb95533af07a3ae43f409
Author: Alexei Sheplyakov <varg at 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 at 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 at 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 at 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.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20071117/fdbe2f05/attachment.pgp


More information about the GiNaC-devel mailing list