Hi, I just thought to give cln a try, but I seem to have hit a bad entry point. 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; } Also, the legendre.cc example segfaults, if it is called with two arguments Ralf
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/>
Am Dienstag, 8. März 2005 00:55 schrieb Richard B. Kreckel:
On Mon, 7 Mar 2005, Ralf Goertz wrote: [...]
Could you please play a bit with that patch and tell how it goes?
I would love to but there is another problem I haven't mentioned so far. I can't "make" cln! That is, make compiles everything fine and creates the library but it contains unresolved symbols. So far I couldn't find out what the problem is: g++ -Wall -O2 -fno-exceptions exam.o exam_I.o exam_RA.o exam_SF.o exam_FF.o exam_DF.o exam_LF.o exam_I_gcd.o exam_I_sqrtp.o -o .libs/exam ../src/.libs/libcln.so /usr/lib/libgmp.so -lm exam.o(.text+0x42): In function `_GLOBAL__I__Z15test_elementaryv': /home/rg/tmp/cln-1.1.9/tests/exam.s:67: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_SF.o(.text+0x41): In function `_GLOBAL__I__Z11test_sfloatv': /home/rg/tmp/cln-1.1.9/tests/exam_SF.s:6255: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_FF.o(.text+0x41): In function `_GLOBAL__I__Z11test_ffloatv': /home/rg/tmp/cln-1.1.9/tests/exam_FF.s:6261: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_FF.o(.text+0x46):/home/rg/tmp/cln-1.1.9/tests/exam_FF.s:6262: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_DF.o(.text+0x41): In function `_GLOBAL__I__Z11test_dfloatv': /home/rg/tmp/cln-1.1.9/tests/exam_DF.s:6802: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_DF.o(.text+0x46):/home/rg/tmp/cln-1.1.9/tests/exam_DF.s:6803: more undefined references to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' follow ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_SV_ringelt__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_GV_number__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_GV_I__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_SV_number__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_symbol__firstglobalfun' collect2: ld returned 1 exit status Ralf
On Tue, 8 Mar 2005, Ralf Goertz wrote:
Am Dienstag, 8. März 2005 00:55 schrieb Richard B. Kreckel:
Could you please play a bit with that patch and tell how it goes?
I would love to but there is another problem I haven't mentioned so far. I can't "make" cln! That is, make compiles everything fine and creates the library but it contains unresolved symbols. So far I couldn't find out what the problem is:
Which leaves me wondering how you were able to find the bug.
g++ -Wall -O2 -fno-exceptions exam.o exam_I.o exam_RA.o exam_SF.o exam_FF.o exam_DF.o exam_LF.o exam_I_gcd.o exam_I_sqrtp.o -o .libs/exam ../src/.libs/libcln.so /usr/lib/libgmp.so -lm exam.o(.text+0x42): In function `_GLOBAL__I__Z15test_elementaryv': /home/rg/tmp/cln-1.1.9/tests/exam.s:67: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_SF.o(.text+0x41): In function `_GLOBAL__I__Z11test_sfloatv': /home/rg/tmp/cln-1.1.9/tests/exam_SF.s:6255: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_FF.o(.text+0x41): In function `_GLOBAL__I__Z11test_ffloatv': /home/rg/tmp/cln-1.1.9/tests/exam_FF.s:6261: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_FF.o(.text+0x46):/home/rg/tmp/cln-1.1.9/tests/exam_FF.s:6262: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_DF.o(.text+0x41): In function `_GLOBAL__I__Z11test_dfloatv': /home/rg/tmp/cln-1.1.9/tests/exam_DF.s:6802: undefined reference to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' exam_DF.o(.text+0x46):/home/rg/tmp/cln-1.1.9/tests/exam_DF.s:6803: more undefined references to `_GLOBAL__I_cl_module__cl_ieee__firstglobalfun' follow ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_SV_ringelt__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_GV_number__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_GV_I__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_SV_number__firstglobalfun' ../src/.libs/libcln.so: undefined reference to `_GLOBAL__I_cl_module__cl_symbol__firstglobalfun' collect2: ld returned 1 exit status
What system is this? Please submit the output of `uname -a', the output of `g++ -v' and also the way you configured CLN (CXXFLAGS and such). -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Am Dienstag, 8. März 2005 14:08 schrieb Richard B. Kreckel:
On Tue, 8 Mar 2005, Ralf Goertz wrote:
Am Dienstag, 8. März 2005 00:55 schrieb Richard B. Kreckel:
Could you please play a bit with that patch and tell how it goes?
I would love to but there is another problem I haven't mentioned so far. I can't "make" cln! That is, make compiles everything fine and creates the library but it contains unresolved symbols. So far I couldn't find out what the problem is:
Which leaves me wondering how you were able to find the bug.
Well, as I said, I used the debuging binary rpm from the ftp server.
What system is this? Please submit the output of `uname -a', the output of `g++ -v' and also the way you configured CLN (CXXFLAGS and such).
I would have given the details in my previous mail, but I thought I could figure out myself what the problem was. But I failed... :-( ------- uname -a Linux big 2.6.8-24.11-default #1 Fri Jan 14 13:01:26 UTC 2005 i686 athlon i386 GNU/Linux g++ -v Reading specs from /usr/lib/gcc-lib/i586-suse-linux/3.3.4/specs Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --enable-languages=c,c++,f77,objc,java,ada --disable-checking --libdir=/usr/lib --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit i586-suse-linux Thread model: posix gcc version 3.3.4 (pre 3.3.5 20040809) CXXFLAGS="-Wall -O2 -fno-exceptions" ./configure --with-gmp but also ./configure --with-gmp ---------------------- SuSE has a history of prematurely using new versions of gcc. But I haven't been coding very much lately, therefore I'm not up to date with the current development. Ralf
On Tue, 8 Mar 2005, Ralf Goertz wrote:
What system is this? Please submit the output of `uname -a', the output of `g++ -v' and also the way you configured CLN (CXXFLAGS and such).
I would have given the details in my previous mail, but I thought I could figure out myself what the problem was. But I failed... :-(
------- uname -a Linux big 2.6.8-24.11-default #1 Fri Jan 14 13:01:26 UTC 2005 i686 athlon i386 GNU/Linux
g++ -v Reading specs from /usr/lib/gcc-lib/i586-suse-linux/3.3.4/specs Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --enable-languages=c,c++,f77,objc,java,ada --disable-checking --libdir=/usr/lib --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit i586-suse-linux Thread model: posix gcc version 3.3.4 (pre 3.3.5 20040809)
CXXFLAGS="-Wall -O2 -fno-exceptions" ./configure --with-gmp
but also
./configure --with-gmp
----------------------
SuSE has a history of prematurely using new versions of gcc. But I haven't been coding very much lately, therefore I'm not up to date with the current development.
Yes, I vaguely remember a problem of this kind. But I am under the impression that it was with an earlier compiler. Which version of SuSE is this? Anyway, regarding your original problem: I've been chasing my tail for a while to find the memory leak that making the dtor non-virtual must surely introduce (because those objects _are_ deleted by base-pointer). Well, it turns out there isn't one, because none of the dtors seems to be doing something special and simply freeing the memory is enough. Still, I would like that to be _really_ fixed. I think the final patch will just make cl_heap_modint_ring and cl_heap_univpoly_ring (and their subclasses) nonvirtual, too. But in addition I'll introduce an additional cl_class object for each of those subclasses and store it in the type field (just as usual) while taking care that the dtor is hooked in the cl_class objects. That should cure it. I have no idea why the vptr was introduced. We have all the infrastructure we need by virtue of cl_class. Why not use it? Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Am Dienstag, 8. März 2005 16:13 schrieb Richard B. Kreckel:
On Tue, 8 Mar 2005, Ralf Goertz wrote:
SuSE has a history of prematurely using new versions of gcc. But I haven't been coding very much lately, therefore I'm not up to date with the current development.
Yes, I vaguely remember a problem of this kind. But I am under the impression that it was with an earlier compiler. Which version of SuSE is this?
It's SuSE 9.2. Although I have programmed in c++, I am not an expert. Therefore, I might be missing something. But when I tried to locate the unresolved symbols I found e.g. in include/SV_number.h struct cl_SV_number : public cl_SV<cl_number,cl_SV_any> { ... }; Why "struct"? Shouldn't it be a class? I just changed it to "class" and at least it is compiling (although in the library the symbol is still missing)
Anyway, regarding your original problem: I've been chasing my tail for a while to find the memory leak that making the dtor non-virtual must surely introduce (because those objects _are_ deleted by base-pointer). Well, it turns out there isn't one, because none of the dtors seems to be doing something special and simply freeing the memory is enough. Still, I would like that to be _really_ fixed.
So would I. I'd like to do some Galois field computations, that's how I came to try cln. Ralf
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/>
My latest findings: On Sat, 12 Mar 2005, I wrote:
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?
Of course, taking the cl_heap* part of a cl_heap_modint_ring* results in an offset the size of the vptr. And for it to work it's required that the definitions are visible. Otherwise the offset will be zero. Owwww, this is soo painful! This is a first patch (two, actually). But it's still not enough to make it work properly: diff -a -u -r1.5 modinteger.h --- modinteger.h 6 May 2002 10:29:18 -0000 1.5 +++ modinteger.h 14 Mar 2005 22:38:26 -0000 @@ -37,8 +37,7 @@ // Assignment operator. cl_modint_ring& operator= (const cl_modint_ring&); // Automatic dereferencing. - cl_heap_modint_ring* operator-> () const - { return (cl_heap_modint_ring*)heappointer; } + cl_heap_modint_ring* operator-> () const; }; // Z/0Z @@ -51,10 +50,6 @@ CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring) CL_DEFINE_ASSIGNMENT_OPERATOR(cl_modint_ring,cl_modint_ring) -// Normal constructor for `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)) {} - // Operations on modular integer rings. inline bool operator== (const cl_modint_ring& R1, const cl_modint_ring& R2) @@ -358,6 +353,13 @@ }; #define SUBCLASS_cl_heap_modint_ring() \ SUBCLASS_cl_heap_ring() + +// Normal constructor for `cl_modint_ring'. +inline cl_modint_ring::cl_modint_ring (cl_heap_modint_ring* r) + : cl_ring ((cl_private_thing) (cl_inc_pointer_refcount(r), (cl_heap*)r)) {} + +inline cl_heap_modint_ring* cl_modint_ring::operator-> () const +{ return (cl_heap_modint_ring*)heappointer; } // Lookup or create a modular integer ring Z/mZ extern const cl_modint_ring find_modint_ring (const cl_I& m); breathless -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On Mon, 14 Mar 2005, I wrote:
Of course, taking the cl_heap* part of a cl_heap_modint_ring* results in an offset the size of the vptr. And for it to work it's required that the definitions are visible. Otherwise the offset will be zero.
However, if one takes care that the pointer of a cl_rcpointer always points to the cl_heap sub-part, one runs into serious trouble later. In src/base/cl_free.cc: void cl_free_heap_object (cl_heap* pointer) { // This is invoked when pointer->refcount gets decremented to 0. var const cl_class* type = pointer->type; if (type->destruct) type->destruct(pointer); free_hook(pointer); } This calls only the registered dtor of the subobject, which invokes undefined behavior! (In practice, "undefined" means a downright segfault, in this case.) I see no way to cure this problem without adding more indirection. The best idea I'm currently having is removing the vptr from all classes derived from cl_heap. This is done in the attached patch. It makes each subclass of cl_heap_modint_ring have different cl_class* type, however, so they cannot be compared any more! For this reason, it is best to remove the extern declaration of the static cl_class_modint_ring and rely on cl_class::flags for run time type information. (There goes a clear design.) If somebody wants to bang on the patch, I'm interested in hearing how it goes. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (2)
-
Ralf Goertz
-
Richard B. Kreckel