[CLN-list] Segfault when using univpoly

Richard B. Kreckel kreckel at ginac.de
Sat Mar 12 01:36:47 CET 2005


On Tue, 8 Mar 2005, Richard B. Kreckel wrote:
> On Mon, 7 Mar 2005, Ralf Goertz wrote:
> > 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.

No it isn't undefined.  My analysis above was incorrect, I'm afraid.

Rather, some debugging has revealed that we are having some sort of
type-punning problem in include/cln/modinteger.h.  It happens in the ctor
from cl_modint_ring*:

inline cl_modint_ring::cl_modint_ring (cl_heap_modint_ring* r)
        : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount((cl_heap*)r), r)) {}

The code generated by this function stomps on the type* member variable of
cl_heap_modint_ring (inherited from cl_heap).  I am unable to see why,
though.  Anyone else sees clearer?  Oh, yes, the fact that it stomps on
type* has something to do with the vptr being there or not.  But what?

For one thing, there is a little inversion problem, as becomes apparant by
the need to cast r to a cl_heap*.  That should not be needed, because
cl_heap is the base class of cl_heap_modint_ring.  However,
cl_heap_modint_ring is defined further down in that header file!  So, the
compiler could hardly guess that the two are related.  So, if we put
that ctor below the definition of cl_heap_modint_ring we get away without
the cast.  But that doesn't seem to be enough, though.

Rewriting it in a dumb straightforward way:

inline cl_modint_ring::cl_modint_ring (cl_heap_modint_ring* r)
{
        heappointer = r;
        cl_inc_pointer_refcount(heappointer);
}

Theoretically, this solves the crash observed by Ralf.  However, it
introduces another one because the immediate base class of cl_modint_ring
is cl_ring and we're now calling the base class' default ctor which tries
to reference cl_no_ring (see include/cln/ring.h:373).  Maybe this can be
cured by introducing CL_PROVIDE(cl_no_ring) in include/cln/modinteger.h...

Anyway, this is not a solution.  It's no more than a poorly understood
workaround.  Can anybody shed some light on this issue?

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





More information about the CLN-list mailing list