[CLN-list] Segfault when using univpoly

Richard B. Kreckel kreckel at ginac.de
Tue Mar 8 00:55:07 CET 2005


On Mon, 7 Mar 2005, Ralf Goertz wrote:
> I just thought to give cln a try, but I seem to have hit a bad entry point.

Indeed.

> The following program segfaults
>
> %---------------------------------
> #include<iostream>
> #include<cln/cln.h>
>
> using namespace cln;
> using namespace std;
>
> main(){
>         cl_modint_ring R=find_modint_ring(9811);
>         cl_univpoly_modint_ring P=find_univpoly_ring(R);
>         return 0;
> }
> %--------------------------------------
>
> Using the 1.1.9-debug.rpm on a SuSE 9.2 linux, this is the output of gdb
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x400fe50c in cln::cl_make_univpoly_ring (r=@0xbfffefb0) at object.h:475
> 475                     { return heappointer->type; }

Ouch!  This is an ugly bug and I'm not quite sure how to fix it.

The problem is with the descendants of struct cl_heap.  In
include/cln/object.h:164 there is:

struct cl_heap {
    int refcount;                  // reference count for garbage collection
    const struct cl_class * type;  // type tag for dynamic typing
};

But in include/cln/modinteger.h:209 there is:

class cl_heap_modint_ring : public cl_heap {
    // ...
// This class is intented to be subclassable, hence needs a virtual destructor.
    virtual ~cl_heap_modint_ring () {}
private:
    virtual void dummy ();
};

At this point, the two virtual functions introduce a vptr to each object
of class cl_heap_modint_ring.  By the way, note that the same happens to
class cl_heap_univpoly_ring.

Now, in your program you call find_univpoly_ring(const cl_ring& r) where
r is of dynamic type cl_modint_ring.  It determines that the ring does not
exist yet and calls cl_make_univpoly_ring(const cl_ring& r) with in turn
invokes r.pointer_type().  But that is actually:

const cl_class * cl_rcpointer::pointer_type() const
{ return heappointer->type; }

Since heappointer is of static type cl_heap but of dynamic type
cl_heap_modint_ring (with vptr!), referencing cl_heap::type member
variable is undefined.

Possible fixes that I'm able to think up in a hurry:

1) Kluge around by overriding *::pointer_type() for certain classes:
   const cl_class * cl_modint_ring::pointer_type () const
   { return (reinterpret_cast<cl_heap_modint_ring*>(heappointer))->type; }
   This might fix some such problems but cannot work in general since it
   assumes that it is always called with the right dynamic type, otherwise
   the (wrong) function from cl_heap will be called.  And we simply cannot
   tell statically whether it's a cl_heap_modint_ring or a, say,
   cl_heap_ring (without vptr!)  Also note that writing
   const cl_class * cl_modint_ring::pointer_type () const
   { return ((cl_heap_modint_ring*)(heappointer))->type; }
   would be subtly wrong.

2) Add a vptr to cl_heap by giving it a virtual destructor.
   Ugh!  There must be a reason why we aren't writing in Java in the
   first place, I assume.  Anyway, I don't think it's going to be solved
   trivially.

3) Remove the vptr from cl_heap_modint_ring (and also from
   cl_heap_univpoly_ring) for good.  I'm irritated by the comment in
   include/cln/modinteger.h:354: "This class is intented to be
   subclassable, hence needs a virtual destructor."  The classes that
   actually do subclass it don't do anything to the virtual functions
   (with the sole exception of the destructors.)  So, this quick and dirty
   patch seems the fix your problem, maybe at the risk of a small memory
   leak.  That must yet be analyzed.
-------------------------------------------------------------------
Index: include/cln/modinteger.h
===================================================================
RCS file: /home/cvs/cln/include/cln/modinteger.h,v
retrieving revision 1.5
diff -a -u -r1.5 modinteger.h
--- include/cln/modinteger.h    6 May 2002 10:29:18 -0000       1.5
+++ include/cln/modinteger.h    7 Mar 2005 23:41:22 -0000
@@ -352,9 +352,9 @@
 // Constructor.
        cl_heap_modint_ring (cl_I m, cl_modint_setops*, cl_modint_addops*, cl_modint_mulops*);
 // This class is intented to be subclassable, hence needs a virtual destructor.-       virtual ~cl_heap_modint_ring () {}
+       //virtual ~cl_heap_modint_ring () {}
 private:
-       virtual void dummy ();
+       //virtual void dummy ();
 };
 #define SUBCLASS_cl_heap_modint_ring() \
   SUBCLASS_cl_heap_ring()
Index: include/cln/univpoly.h
===================================================================
RCS file: /home/cvs/cln/include/cln/univpoly.h,v
retrieving revision 1.5
diff -a -u -r1.5 univpoly.h
--- include/cln/univpoly.h      1 Jan 2004 15:59:30 -0000       1.5
+++ include/cln/univpoly.h      7 Mar 2005 23:41:26 -0000
@@ -341,9 +341,9 @@
 // Constructor.
        cl_heap_univpoly_ring (const cl_ring& r, cl_univpoly_setops*, cl_univpoly_addops*, cl_univpoly_mulops*, cl_univpoly_modulops*, cl_univpoly_polyops*);
 // This class is intented to be subclassable, hence needs a virtual destructor.-       virtual ~cl_heap_univpoly_ring () {}
+       //virtual ~cl_heap_univpoly_ring () {}
 private:
-       virtual void dummy ();
+       //virtual void dummy ();
 };
 #define SUBCLASS_cl_heap_univpoly_ring() \
   SUBCLASS_cl_heap_ring()
Index: src/modinteger/cl_MI.cc
===================================================================
RCS file: /home/cvs/cln/src/modinteger/cl_MI.cc,v
retrieving revision 1.4
diff -a -u -r1.4 cl_MI.cc
--- src/modinteger/cl_MI.cc     29 Jun 2003 12:32:51 -0000      1.4
+++ src/modinteger/cl_MI.cc     7 Mar 2005 23:41:31 -0000
@@ -62,7 +62,7 @@

 // This tells the compiler to put the `cl_heap_modint_ring' vtable
 // into this file.
-void cl_heap_modint_ring::dummy () {}
+//void cl_heap_modint_ring::dummy () {}


 static cl_boolean modint_equal (cl_heap_modint_ring* R, const _cl_MI& x, const _cl_MI& y)
Index: src/polynomial/elem/cl_UP.cc
===================================================================
RCS file: /home/cvs/cln/src/polynomial/elem/cl_UP.cc,v
retrieving revision 1.2
diff -a -u -r1.2 cl_UP.cc
--- src/polynomial/elem/cl_UP.cc        28 Aug 2000 22:08:21 -0000      1.2
+++ src/polynomial/elem/cl_UP.cc        7 Mar 2005 23:41:31 -0000
@@ -58,7 +58,7 @@

 // This tells the compiler to put the `cl_heap_univpoly_ring' vtable
 // into this file.
-void cl_heap_univpoly_ring::dummy () {}
+//void cl_heap_univpoly_ring::dummy () {}


 // Create a new univariate polynomial ring.
-------------------------------------------------------------------

Could you please play a bit with that patch and tell how it goes?

Also, it might be helpful to consider the polynomial sector in CLN as,
errhm, "unfinished".  :-/

> Also, the legendre.cc example segfaults, if it is called with two arguments

Same cause, same solution.  Interesting, though.  How could it have
worked?  Was the virtual stuff introduced later then that example?

Regards
  -richy.
-- 
Richard B. Kreckel
<http://www.ginac.de/~kreckel/>





More information about the CLN-list mailing list