[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