| Karim Belabas on Tue, 27 Aug 2002 14:38:38 +0200 (CEST) |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| Re: Heap memory leak in Pari/GP 2.1.4 during vector operations. |
[Alexander Shumakovitch:]
> After some tries, I've managed to trace down the problem to initializations
> of vectors (or matrices) whose entries are going to be vectors as well. I
> used to do it in one operator. But in this case assignment of arbitrary
> values to elements of those vectors grabs some blocks on heap, which are
> not freed even after doing kill().
>
> Here is how to trigger the bug:
> (20:35) gp > v=vector(2,i,vector(i));v[2][1]=5;getheap
> time = 0 ms.
> %2 = [34, 225]
> (20:35) gp > v=vector(2,i,vector(i));v[2][1]=5;getheap
> time = 0 ms.
> %3 = [35, 232]
Please, try the following patch [or, better, upgrade from CVS stable branch].
I wrote the original code about 8 years ago now [to implement linear time
assignment to GP arrays, former was quadratic in the most favourable
case...], and it should have been junked long ago.
Basic assumption was that 1 level of recursion from the toplevel structure
was enough. The new code is simpler, more robust [and correctly documented],
but possibly a bit slower when huge multidimensional arrays are involved. I
don't see any way around this without implementing a full-fledged garbage
collector [which would probably end up being slower for ordinary scripts...]
Index: init.c
===================================================================
RCS file: /home/megrez/cvsroot/pari/src/language/init.c,v
retrieving revision 1.158
retrieving revision 1.159
diff -c -r1.158 -r1.159
*** src/language/init.c 2002/08/25 22:21:41 1.158
--- src/language/init.c 2002/08/27 12:12:10 1.159
***************
*** 658,669 ****
return cur_bloc = x;
}
! void
! killbloc0(GEN x, int inspect)
{
! long tx,lx,l,i,j;
! GEN p1;
if (!x || isonstack(x)) return;
if (bl_next(x)) bl_prev(bl_next(x)) = bl_prev(x);
else
--- 658,689 ----
return cur_bloc = x;
}
! /* recursively look for clones in the container and kill them */
! static void
! inspect(GEN x)
{
! long i, lx;
! switch(typ(x)) /* HACK: if x is not a GEN, we have typ(x)=0 */
! {
! case t_VEC: case t_COL: case t_MAT:
! lx = lg(x);
! for (i=1;i<lx;i++) inspect((GEN)x[i]);
! break;
! case t_LIST:
! lx = lgef(x);
! for (i=2;i<lx;i++) inspect((GEN)x[i]);
! break;
! }
! if (isclone(x)) gunclone(x); /* Don't inspect here! components are dead */
! }
+ /* If insp is set, recursively inspect x, killing all clones found. The GP
+ * expression x[i] = y is implemented as x[i] := gclone(y) and we need to
+ * reclaim the memory. Useless to inspect when x does not correspond to a GP
+ * variable [not dangerous, though] */
+ void
+ killbloc0(GEN x, int insp)
+ {
if (!x || isonstack(x)) return;
if (bl_next(x)) bl_prev(bl_next(x)) = bl_prev(x);
else
***************
*** 674,718 ****
if (bl_prev(x)) bl_next(bl_prev(x)) = bl_next(x);
if (DEBUGMEM > 2)
fprintferr("killing bloc (no %ld): %08lx\n", bl_num(x), x);
! if (inspect)
! {
! /* FIXME: SIGINT should be blocked at this point */
! tx=typ(x); /* if x is not a GEN, we will have tx=0 */
! if (is_vec_t(tx))
! {
! lx = lg(x);
! for (i=1;i<lx;i++)
! {
! p1=(GEN)x[i];
! if (isclone(p1)) killbloc(p1);
! }
! }
! else if (tx==t_MAT)
! {
! lx = lg(x);
! if (lx>1)
! {
! l=lg(x[1]);
! if (l>1)
! for (i=1;i<lx;i++)
! for (j=1;j<l;j++)
! {
! p1=gmael(x,i,j);
! if (isclone(p1)) killbloc(p1);
! }
! }
! }
! else if (tx==t_LIST)
! {
! lx = lgef(x);
! for (i=2;i<lx;i++)
! {
! p1=(GEN)x[i];
! if (isclone(p1)) killbloc(p1);
! }
! }
! unsetisclone(x);
! /* FIXME: SIGINT should be released here */
}
free((void *)bl_base(x));
}
--- 694,703 ----
if (bl_prev(x)) bl_next(bl_prev(x)) = bl_next(x);
if (DEBUGMEM > 2)
fprintferr("killing bloc (no %ld): %08lx\n", bl_num(x), x);
! if (insp)
! { /* FIXME: SIGINT should be blocked until inspect() returns */
! unsetisclone(x); /* important: oo recursion otherwise */
! inspect(x);
}
free((void *)bl_base(x));
}
--
Karim Belabas Tel: (+33) (0)1 69 15 57 48
Dép. de Mathematiques, Bat. 425 Fax: (+33) (0)1 69 15 60 19
Université Paris-Sud Email: Karim.Belabas@math.u-psud.fr
F-91405 Orsay (France) http://www.math.u-psud.fr/~belabas/
--
PARI/GP Home Page: http://www.parigp-home.de/